我正在使用Map of Threads和相关的runnable对象来跟踪runnables。当抛出interruptedException
时,我想要访问当前线程及其可运行对象。
Map<Thread, Runnable> myMap = new Map<Thread, Runnable>();
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(new myRunnable());
但是当我将runnable添加到线程池时,我想不出一种填充Map的方法。
如何在包含Thread及其runnable对象的地图中添加一个条目?
答案 0 :(得分:3)
您可以使用ThreadPoolExecutor的钩子方法:
final Map<Runnable, Thread> map = new ConcurrentHashMap<Runable, Thread>();
ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()) {
@Override
protected void beforeExecute(Thread t, Runnable r) {
map.put(r, t);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
map.remove(r);
}
};
答案 1 :(得分:3)
你从错误的角度接近它。提交到主题后,您应该认为您的工作已经完成。发生的任何中断都应由执行线程处理。
例如
public void run(){
try{
//do some work that responds to interruption
}catch(InterruptedException ex){
//clean up
}
}
或者
public void run(){
if(Thread.currentThread().isInterrtuped()){
//clean up
return;
}
]
答案 2 :(得分:1)
ExecutorService背后的想法是从正在使用的线程中抽象出来。您可以覆盖myRunnable以泄漏信息。
所以你打电话给
pool.execute(new myRunnable(myMap));
然后在myRunnable中让构造函数保存对myMap的引用并添加
myMap.put(this,originalRunnableObject)
到run方法 - 其中originalRunnableObject是对此的保存引用。当然你需要你的地图是一个并发的地图(你不能像你想要的那样实例化地图界面)。
然而,我必须首先问你为什么要这样做,因为我说Executor应该提供一个你似乎想要颠覆的抽象层。
答案 3 :(得分:0)
// Map might cause concurrent modifications, Queue may be a better choice.
final BlockingQueue<Pair<Thread, Runnable>> interruptedRunnable = new LinkedBlockingDeque<>(0);
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
// TODO do something here?
if (Thread.interrupted()) {
interruptedRunnable.add(Pair.of(Thread.currentThread(), this));
return;
}
} catch (InterruptedException _) {
interruptedRunnable.add(Pair.of(Thread.currentThread(), this));
}
}
});
// TODO polling ...
while (true) {
try {
// TODO adjust timeout
Pair<Thread, Runnable> x = interruptedRunnable.poll(1, TimeUnit.MINUTES);
if (null != x) {
// check x.
}
// TODO
} catch (InterruptedException _) {
break;
}
}