任务调度线程池。
Timer 缺点
在「任务调度线程池」功能加入之前,可以使用 java.util.Timer 来实现定时功能,Timer 的有点在于简单。
但是,由于所有任务都是由一个线程来调度,因此,所有的任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.redisc;
import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j;
import java.util.*; import java.util.concurrent.*;
@Slf4j(topic = "c.Test") public class Run {
public static void main(String[] args) throws InterruptedException, ExecutionException { Timer timer = new Timer(); TimerTask task1 = new TimerTask() { @SneakyThrows @Override public void run() { log.debug("task1"); Thread.sleep(2000); } }; TimerTask task2 = new TimerTask() { @Override public void run() { log.debug("task2"); } };
log.debug("start..."); timer.schedule(task1,1000); timer.schedule(task2,1000); } }
|
期望两个任务都是 1
秒后执行,但是,实际输出
1 2 3
| 22:56:02.714 [main] DEBUG c.Test - start... 22:56:03.719 [Timer-0] DEBUG c.Test - task1 22:56:05.723 [Timer-0] DEBUG c.Test - task2
|
如果 task1
有异常,那么,task2
不会执行。
ScheduledThreadPoolExecutor 基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.redisc;
import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j;
import java.util.*; import java.util.concurrent.*;
@Slf4j(topic = "c.Test") public class Run {
public static void main(String[] args) throws InterruptedException, ExecutionException { ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
pool.schedule(() -> { log.debug("task1"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }, 1, TimeUnit.SECONDS);
pool.schedule(() -> { log.debug("task2"); }, 1, TimeUnit.SECONDS); } }
|
输出
1 2
| 22:14:16.744 [pool-1-thread-2] DEBUG c.Test - task2 22:14:16.744 [pool-1-thread-1] DEBUG c.Test - task1
|
两个同时执行。即便是任务出现异常,也不影响其他线程。
ScheduledThreadPoolExecutor 定时执行
scheduleAtFixedRate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;
@Slf4j(topic = "c.Test") public class Run {
public static void main(String[] args) throws InterruptedException, ExecutionException { ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
pool.scheduleAtFixedRate(() -> { log.debug("1"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }, 1, 1, TimeUnit.SECONDS);
} }
|
输出
1 2 3 4 5
| 22:25:27.925 [pool-1-thread-1] DEBUG c.Test - 1 22:25:29.931 [pool-1-thread-1] DEBUG c.Test - 1 22:25:31.932 [pool-1-thread-1] DEBUG c.Test - 1 22:25:33.934 [pool-1-thread-1] DEBUG c.Test - 1 22:25:35.935 [pool-1-thread-1] DEBUG c.Test - 1
|
仔细看,任务共消耗 2s
,当执行完任务后,其就立刻执行。
scheduleWithFixedDelay
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;
@Slf4j(topic = "c.Test") public class Run {
public static void main(String[] args) throws InterruptedException, ExecutionException { ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
pool.scheduleWithFixedDelay(() -> { log.debug("1"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }, 1, 1, TimeUnit.SECONDS); } }
|
输出
1 2 3 4
| 22:27:40.122 [pool-1-thread-1] DEBUG c.Test - 1 22:27:43.130 [pool-1-thread-1] DEBUG c.Test - 1 22:27:46.137 [pool-1-thread-1] DEBUG c.Test - 1 22:27:49.145 [pool-1-thread-1] DEBUG c.Test - 1
|
任务执行完毕,然后又开始延迟 1s
执行。