[Java] What happens when java timing tasks are scheduled every second

Insert picture description here

1 Overview

Because of the need, I wrote a program in the code to schedule once a second to perform some tasks that are not very short, but I don’t know the specific time, but this service has a problem on the spot, and then when the code is reviewed, I feel that this is every second It was too fast once. Will there be one that has not been executed yet. Another schedule starts again? Then the scene overlapped, resulting in many threads in memory.

I did an experiment

package com.java.thread.demo.schedule;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author: chuanchuan.lcc
 * @date: 2020-12-22 10:52
 * @modifiedBy: chuanchuan.lcc
 * @version: 1.0
 * @description: 定时任务
 */
public class ScheduleTask {
    
    

    private static ScheduledExecutorService scheduledExecutorService;

    private static AtomicLong atomicLong = new AtomicLong(0L);

    public static void main(String[] args) throws InterruptedException {
    
    
        scheduledExecutorService = Executors.newScheduledThreadPool(3);

        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                atomicLong.incrementAndGet();
                try {
    
    
                    long start = System.currentTimeMillis();
                    for (long i = 0; i < 10000000000L; i++) {
    
    

                    }
                    long end = System.currentTimeMillis();
                    System.out.println((end -start)/1000);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
                long count = atomicLong.decrementAndGet();
                System.out.println("当前线程个数:" + count);
            }
        }, 0, 1, TimeUnit.SECONDS);

        Thread.sleep(Integer.MAX_VALUE);
    }


}

Execute as follows

4
当前线程个数:0
3
当前线程个数:0
3
当前线程个数:0
3

I found that it is not what I imagined. I set the running time to be about 3 seconds and the scheduling time to once every 1 second. It stands to reason that new threads should always be generated during the calculation, but this is not the case. Only one thread is executed. , The next thread will start scheduling.

2. Source code

Thread creation

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    
    
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    
    
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    
    
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

It can be seen that the final call is ThreadPoolExecutor, but the parameter is passed. The Integer.MAX_VALUE,thread is infinite. This is very unsafe and may lead to OOM

The queue here is DelayedWorkQueue, this queue is a blocking queue

   /**
     * Specialized delay queue. To mesh with TPE declarations, this
     * class must be declared as a BlockingQueue<Runnable> even though
     * it can only hold RunnableScheduledFutures.
     */
    static class DelayedWorkQueue extends AbstractQueue<Runnable>
        implements BlockingQueue<Runnable> {
    
    

For other explanations, please refer to: Add link description

Guess you like

Origin blog.csdn.net/qq_21383435/article/details/111526309