public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
他的特点是:
核心线程数和最大线程数都是1
线程保活时间是0,就是说执行完,线程会被立即销毁,重新创建
工作队列也是使用的LinkedBlockingQueue
CachedThreadPool
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
public class Demo_06_02_1_Exexutors {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("欢迎关注微信公众号'大雄和你一起学编程'"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 3, 1, TimeUnit.SECONDS);
}
}
// 这段代码会在启动后3秒开始输出,然后每隔10秒输出一次
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:36:50 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:37:00 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:37:10 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:37:20 CST 2020
public class Demo_06_02_2_Exexutors {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
scheduledExecutorService.scheduleWithFixedDelay(() -> {
System.out.println("欢迎关注微信公众号'大雄和你一起学编程'"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 3, 1, TimeUnit.SECONDS);
}
}
// 这段代码会在启动后3秒开始输出,然后每隔10+1秒输出一次
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:40:18 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:40:29 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:40:40 CST 2020
// 欢迎关注微信公众号'大雄和你一起学编程'Fri May 08 09:40:51 CST 2020
这两者的区别大家可以体会下
ScheduledThreadPool 有四种方式创建
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ExecutorService newSingleThreadExecutor()
// 还有两个是可以指定线程工厂
提交任务主要有两种方式
// 他会每间隔一个固定时间执行一次,如果你的任务执行时间<=你给定的period, 那么每隔period时间会执行一次
// 如果你的任务执行时间>你给的period, 那么任务执行完就开始下一次
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit)
// 他不管你的任务执行时间,任务执行完了再隔delay时间执行下一次任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit)
// 决定两个Task的time相同时谁排在前面,是用一个AtomicLong搞出来的
private final long sequenceNumber;
// Task下一次将要被执行的具体时间
private long time;
// 任务执行的间隔时间,正数表示用fixed-rate(scheduleAtFixedRate)方式, 负数表示用fixed-delay(scheduleWithFixedDelay)方式
private final long period;
// 用于下一次加入队列
RunnableScheduledFuture<V> outerTask = this;
// 优化用的
int heapIndex;
方法如下:
public long getDelay(TimeUnit unit) {
return unit.convert(time - now(), NANOSECONDS);
}
计算还有多久到执行时间点,这个Delayed接口的getDelay方法一样
public int compareTo(Delayed other) {
if (other == this) // compare zero if same object
return 0;
if (other instanceof ScheduledFutureTask) {
ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
long diff = time - x.time;
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else if (sequenceNumber < x.sequenceNumber)
return -1;
else
return 1;
}
long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
确定排序规则,谁先到期谁排前面,同时到期的,看谁先创建,先创建的排在前面
// 设置下一次要什么时候执行
private void setNextRunTime() {
long p = period;
if (p > 0)
time += p; // 以固定频率执行的任务走这里
else // 以固定时间间隔执行的走这里
time = triggerTime(-p);
}
// 取消任务
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = super.cancel(mayInterruptIfRunning);
if (cancelled && removeOnCancel && heapIndex >= 0)
remove(this);
return cancelled;
}
public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
// 取消
cancel(false);
else if (!periodic)
// 不是周期任务,直接run就好, 执行的FutureTask的run, 执行具体的任务
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) { // runAndReset()可以理解为就是开始执行任务
// 设置 下一次执行时间,注意固定频率和固定间隔的区别
setNextRunTime();
// 再返回队列
reExecutePeriodic(outerTask);
}
}
scheduleAtFixedRate的执行流程
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) {
// 一些参数校验
if (command == null || unit == null)
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
// 构造RunnableScheduledFuture
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
//
triggerTime(initialDelay, unit),
unit.toNanos(period));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
// 下一次加到队列的任务设置好
sft.outerTask = t;
// 延迟执行
delayedExecute(t);
return t;
}
private void delayedExecute(RunnableScheduledFuture<?> task) {
if (isShutdown())
reject(task);
else {
// 加入队列
super.getQueue().add(task);
if (isShutdown() &&
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task))
// 取消任务的情况
task.cancel(false);
else
// 准备开始跑了
ensurePrestart();
}
}
void ensurePrestart() {
// 看现在有几个工作线程
int wc = workerCountOf(ctl.get());
if (wc < corePoolSize) // 当前worker小于核心线程数,加worker
addWorker(null, true);
else if (wc == 0)
// 如果没有的话,不管三七二十一,加worker
addWorker(null, false);
// 加worker以后线程就会启动去工作队列拿任务执行了, 这个普通的线程池是一样的
}