任务会重试处理,关于scheduleWithFixedDelay定时线程池的使用
需求
循环处理业务,当一个任务正常执行/延时执行后,顺延2s继续执行下一个。一个任务有点慢,所以就取5条吧。
Executors.newScheduledThreadPool()线程池的scheduleWithFixedDelay方法正好有这种处理机制。就姑且一试。
代码
package com.chl.thread.pool;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 定时线程池
* @author chl
*
*/
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+" begin = "+new Date());
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for(int i=0; i<5; i++){ //如果多个线程是有问题的, 单个线程成功
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WorkerThread worker = new WorkerThread("--" +i);
scheduledThreadPool.scheduleWithFixedDelay(worker, 5, 2, TimeUnit.SECONDS);
}
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduledThreadPool.shutdown();
while(!scheduledThreadPool.isTerminated()){
}
System.out.println("Finished all threads");
}
}
class WorkerThread implements Runnable{
private String command;
public WorkerThread(String s){
this.command=s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start"+command.toString()+" Time = "+new Date());
processCommand();
System.out.println(Thread.currentThread().getName()+" End"+command.toString()+" Time = "+new Date());
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
以下是测试结果,
main begin = Fri Nov 06 11:57:09 CST 2020
pool-1-thread-1 Start--0 Time = Fri Nov 06 11:57:15 CST 2020
pool-1-thread-2 Start--1 Time = Fri Nov 06 11:57:16 CST 2020
pool-1-thread-3 Start--2 Time = Fri Nov 06 11:57:17 CST 2020
pool-1-thread-4 Start--3 Time = Fri Nov 06 11:57:18 CST 2020
pool-1-thread-5 Start--4 Time = Fri Nov 06 11:57:19 CST 2020
pool-1-thread-1 End--0 Time = Fri Nov 06 11:57:20 CST 2020
pool-1-thread-2 End--1 Time = Fri Nov 06 11:57:21 CST 2020
pool-1-thread-1 Start--0 Time = Fri Nov 06 11:57:22 CST 2020
pool-1-thread-3 End--2 Time = Fri Nov 06 11:57:22 CST 2020
pool-1-thread-4 End--3 Time = Fri Nov 06 11:57:23 CST 2020
pool-1-thread-2 Start--1 Time = Fri Nov 06 11:57:23 CST 2020
pool-1-thread-5 End--4 Time = Fri Nov 06 11:57:24 CST 2020
pool-1-thread-1 End--0 Time = Fri Nov 06 11:57:27 CST 2020
pool-1-thread-2 End--1 Time = Fri Nov 06 11:57:28 CST 2020
Finished all threads
发现什么问题没?thread-1、thread-2的任务重复执行了。
原因
这里有两个参数可以控制。
a. 线程数: 当变更为1个时,每次只处理一个线程就行了。
b. initialDelay参数, 只要保证线程内的任务执行时间不要超过这个值就不会重试了。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
调整
将 initialDelay参数调整为6依然偶尔会有重试,设置为8后,不在出现
测试结果
main begin = Fri Nov 06 13:01:46 CST 2020
pool-1-thread-1 Start--0 Time = Fri Nov 06 13:01:55 CST 2020
pool-1-thread-2 Start--1 Time = Fri Nov 06 13:01:56 CST 2020
pool-1-thread-3 Start--2 Time = Fri Nov 06 13:01:57 CST 2020
pool-1-thread-4 Start--3 Time = Fri Nov 06 13:01:58 CST 2020
pool-1-thread-5 Start--4 Time = Fri Nov 06 13:01:59 CST 2020
pool-1-thread-1 End--0 Time = Fri Nov 06 13:02:00 CST 2020
pool-1-thread-2 End--1 Time = Fri Nov 06 13:02:01 CST 2020
pool-1-thread-3 End--2 Time = Fri Nov 06 13:02:02 CST 2020
pool-1-thread-4 End--3 Time = Fri Nov 06 13:02:03 CST 2020
pool-1-thread-5 End--4 Time = Fri Nov 06 13:02:04 CST 2020
Finished all threads
延伸
这个机制是不是可以利用起来做一些,回调重试处理呢? 有待研究
原创文章,转载请标明本文链接: 任务会重试处理,关于scheduleWithFixedDelay定时线程池的使用