我想实现一个线程池,通过覆盖afterExecute
钩子可以执行某些任务。我可以再次提交参数Runnable r
吗?
这是我的初步实施。
public class RetriableThreadPool extends ThreadPoolExecutor {
static final int MAXRETRYTIMES = 5;
int retryTimes = 0;
public RetriableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
retryTimes = 0;
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (retryTimes < MAXRETRYTIMES) {
retryTimes++;
super.submit(r);
}
}
}
在这个初始实现中,我只允许提交一个任务。
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String[] args) {
RetriableThreadPool retriableThreadPool = new RetriableThreadPool(10, 10, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
retriableThreadPool.execute(new Runnable() {
int num = 0;
@Override
public void run() {
// TODO Auto-generated method stub
num = num + 123;
System.out.println(num);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// retriableThreadPool.shutdown();
}
}
在这个例子中,我得到了奇怪的输出:
123
246
如果可以重新提交runnable,我想我应该得到5个输出。如果无法重新提交。结果只有123。我不明白这个输出的原因。
我感谢nogard修改了代码
public class RetriableThreadPool extends ThreadPoolExecutor {
static final int MAXRETRYTIMES = 5;
int retryTimes = 0;
public RetriableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
retryTimes = 0;
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (retryTimes < MAXRETRYTIMES) {
retryTimes++;
super.execute(r);
}
}
}
我还有其他3个问题:
submit
添加挂钩,就像afterExecute
execute
答案 0 :(得分:1)
我认为此类行为的原因是您在afterExecute方法中提交任务而不是执行,并且提交不会再次触发afterExecute
回调。这就是为什么你在输出中只看到两行:第一行来自原始执行,第二行来自提交。
此外,您永远不会增加重试计数器,您的任务将始终重新提交
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
++ retryTimes;
if (retryTimes < MAXRETRYTIMES) {
super.execute(r);
}
}
更新您的3个问题:
有多种选择:
对于钩子,我会用Decorator模式实现:类似这样:
public class YourExecutor {
@Override
public void submit(Runnable task) {
return super.submit(new TaskDecorator(task));
}
protected void onCompletedTask(Runnable task) {
// callback
}
private class TaskDecorator implements Runnable {
private final Runnable delegate;
public TaskDecorator(Runnable delegate) {
this.delegate = delegate;
}
@Override
public void run() {
this.delegate.run();
onCompletedTask(delegate);
}
}