Task scheduling thread pool

Table of contents

 Timer  

 ScheduledExecutorService

Correctly handle execution task exceptions 


 Timer  

Before the " task scheduling thread pool " function is added, you can use java.util.Timer to implement the timing function. The advantage of Timer is that it is easy to use, but since all tasks are scheduled by the same thread, all tasks are serialized. For execution, only one task can be executed at the same time, and the delay or exception of the previous task will affect the subsequent tasks.

public class Test {
    public static void main(String[] args) {
        Timer timer = new Timer();
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 1");
                sleep(2);
            }
        };
        TimerTask task2 = new TimerTask() {
            @Override

            public void run() {
                log.debug("task 2");
            }
        };
        // 使用 timer 添加两个任务,希望它们都在 1s 后执行
        // 但由于 timer 内只有一个线程来顺序执行队列中的任务,
        //因此『任务1』的延时,影响了『任务2』的执行

        timer.schedule(task1, 1000);
        timer.schedule(task2, 1000);
    }

}

output

20:46:09.444 c.TestTimer [main] - start...

20:46:10.447 c.TestTimer [Timer-0] - task 1

20:46:12.448 c.TestTimer [Timer-0] - task 2  

 ScheduledExecutorService

The thread pool supports timing and periodic execution of tasks. Create a thread pool with corePoolSize as the incoming parameter and the maximum number of threads as the maximum number of integers. 

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

Construction of the ScheduledThreadPoolExecutor class:

   public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue());
    }
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

// 添加两个任务,希望它们都在 1s 后执行

executor.schedule(() -> {
     System.out.println("任务1,执行时间:" + new Date());
     try { Thread.sleep(2000); } catch (InterruptedException e) { }
}, 1000, TimeUnit.MILLISECONDS);

executor.schedule(() -> {
     System.out.println("任务2,执行时间:" + new Date());
}, 1000, TimeUnit.MILLISECONDS);

 output

Task 2, execution time: Fri Jun 23 18:04:46 CST 2023
Task 1, execution time: Fri Jun 23 18:04:46 CST 2023

scheduleAtFixedRate example:

Construction method

    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

 Submits a periodic operation that is enabled first after the given initial delay, and subsequently for the given period of time; that is, execution will begin after initialDelay, then, initialDelay + 2 * period and then initialDelay + period, So on and so forth.

ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

log.debug("start...");

pool.scheduleAtFixedRate(() -> {
 log.debug("running...");
}, 1, 1, TimeUnit.SECONDS);

output 

21:45:43.167 c.TestTimer [main] - start...

21:45:44.215 c.TestTimer [pool-1-thread-1] - running...

21:45:45.215 c.TestTimer [pool-1-thread-1] - running...

21:45:46.215 c.TestTimer [pool-1-thread-1] - running...

21:45:47.215 c.TestTimer [pool-1-thread-1] - running...

scheduleAtFixedRate example (task execution time exceeds interval):  

ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

log.debug("start...");

pool.scheduleAtFixedRate(() -> {
 log.debug("running...");
 sleep(2);
}, 1, 1, TimeUnit.SECONDS);

Output analysis: At the beginning, the delay is 1s, and then, because the task execution time > interval time, the interval is "supported" to 2s

21:44:30.311 c.TestTimer [main] - start...

21:44:31.360 c.TestTimer [pool-1-thread-1] - running...

21:44:33.361 c.TestTimer [pool-1-thread-1] - running...

21:44:35.362 c.TestTimer [pool-1-thread-1] - running...

21:44:37.362 c.TestTimer [pool-1-thread-1] - running...  

scheduleWithFixedDelay example: 

ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

log.debug("start...");

pool.scheduleWithFixedDelay(()-> {
 log.debug("running...");
 sleep(2);
}, 1, 1, TimeUnit.SECONDS);

Output analysis: At the beginning, the delay is 1s, and the interval of scheduleWithFixedDelay is the end of the previous task -> delay -> the start of the next task, so the interval is 3s 

21:40:55.078 c.TestTimer [main] - start...

21:40:56.140 c.TestTimer [pool-1-thread-1] - running...

21:40:59.143 c.TestTimer [pool-1-thread-1] - running...

21:41:02.145 c.TestTimer [pool-1-thread-1] - running...

21:41:05.147 c.TestTimer [pool-1-thread-1] - running...

Evaluation of the entire thread pool shows that the number of threads is fixed, and when the number of tasks is more than the number of threads, it will be queued in an unbounded queue. After the task is executed, these threads will not be released. Used to perform delayed or repeated tasks

Correctly handle execution task exceptions 

Method 1: Actively catch exceptions 

ExecutorService pool = Executors.newFixedThreadPool(1);
pool.submit(() -> {
 try {
     log.debug("task1");
     int i = 1 / 0;
 } catch (Exception e) {
     log.error("error:", e);
 }
})

Method 2: Use Future  

ExecutorService pool = Executors.newFixedThreadPool(1);

Future<Boolean> f = pool.submit(() -> {
     log.debug("task1");
     int i = 1 / 0;
     return true;
});

log.debug("result:{}", f.get());

Guess you like

Origin blog.csdn.net/m0_62436868/article/details/131352720
Recommended