Nig*_*olf 17 java concurrency multithreading executorservice threadpool
我环顾四周但没有找到答案,所以我想确认一下.
假设我有一个固定大小的线程池 - ExecutorService pool = Executors.newFixedThreadPool(5);
我有一些代码:
pool.execute(new Runnable(){
try{
Object waitForMe = doSomethingAndGetObjectToWaitFor();
waitForMe.wait();
doSomethingElse();
}catch(Exception e){ throw new RunTimeException(e) }
});
Run Code Online (Sandbox Code Playgroud)
让我们假设上面的代码被称为几百次.池中只有5个线程(因此上述语句中只有5个应该在一个点上存在).还假设wait()在一个对象上对一个thrid方做了一些I/O调用,并在操作完成时等待回调,所以它自然需要一段时间才能完成.
现在我的问题是当其中一个任务到达a时的行为是什么wait(),任务是否进入休眠状态,然后线程池中的线程从队列中取出另一个任务并开始运行它?
如果正在等待的任务进入睡眠状态,当它获得notify()并唤醒时会发生什么?线程是否返回到线程池的队列(前面或后面)并等待,直到5个线程中的一个可以继续执行它(即调用doSomethingelse())?或者正在执行它的线程是否也进入休眠状态,即5个执行程序线程中的一个正在等待任务(这是我假设的)?或者执行程序线程是否接受另一个任务,并在第一个任务从wait()返回时被中断?
Tom*_*icz 18
wait() 是阻止操作:
导致当前线程等待,直到另一个线程调用notify()方法或notifyAll()
这意味着池中的线程将等待,但从外部看起来当前任务需要花费很多时间才能完成.这也意味着,如果5个任务被执行,他们都wait()中,Executor无法处理剩余的任务是,ekhem,等待在队列中.
确实,执行程序线程本身进入休眠状态,允许其他线程切换并消耗CPU(因此您可以让数百个线程同时等待并且您的系统仍然响应)但仍然线程"无法使用"并被阻止.
另一个有趣的功能是中断 - 如果线程等待某事或睡眠,你可以打断它.请注意,wait()并Thread.sleep()声明InterruptedException.有了ExecutorService你可以通过简单地调用利用这一点:future.cancel()(future就是你得到的回报提交任务时的对象ExecutorService).
最后我想你应该重新设计你的解决方案.而不是主动等待外部系统完成,提供带回调的API:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
Run Code Online (Sandbox Code Playgroud)
这样,外部系统的API将在结果准备就绪时通知您,您不必等待和阻止ExecutorService.最后,如果doSomethingElse()花费大量时间,您甚至可能决定安排它,而不是使用外部第三方I/O线程:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItIsDone(new Callback() {
public void done() {
pool.submit(new Callbale<Void>() {
public Void call() {
doSomethingElse();
}
}
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
Run Code Online (Sandbox Code Playgroud)
更新:您在询问如何处理超时?这是我的想法:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
public void timeout() {
//opps!
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
Run Code Online (Sandbox Code Playgroud)
我猜你可以在第三方实现超时,如果超时发生,只需调用timeout()方法.
| 归档时间: |
|
| 查看次数: |
11879 次 |
| 最近记录: |