Java ExecutorCompletionService不接受Callable返回的项?
我在ExecutorCompletionService有奇怪的行为。该项将添加到ExecutorCompletionService.submit fine。然后它得到处理,并由先前提交的可调用工作线程返回。在返回之后,ExecutorCompletionService.take从未看到它,因此从未看到返回更多项目的阻塞?我真的不知道发生了什么事。我已经创建了打印行,可以看到它完成了可调用的工作线程。一旦发生这种情况,ExecutorCompletionService.take就应该准备好接收,但在某些情况下,它会锁定,有时会出现问题 我已经创建了一个测试用例,如果您运行它几次,您将看到它在某些情况下会被锁定,并且不会占用任何已完成的线程 线程死锁演示Java ExecutorCompletionService不接受Callable返回的项?,java,multithreading,concurrency,Java,Multithreading,Concurrency,我在ExecutorCompletionService有奇怪的行为。该项将添加到ExecutorCompletionService.submit fine。然后它得到处理,并由先前提交的可调用工作线程返回。在返回之后,ExecutorCompletionService.take从未看到它,因此从未看到返回更多项目的阻塞?我真的不知道发生了什么事。我已经创建了打印行,可以看到它完成了可调用的工作线程。一旦发生这种情况,ExecutorCompletionService.take就应该准备好接收,但
import java.util.Observable;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
public class ThreadDeadlockDemo extends Observable implements Runnable {
private CompletionService<String> pool;
private ExecutorService executor ;
private Thread responseWorkerThread;
private HttpSchedulerWorker schedulerWorker;
private boolean shouldRun = true;
private int numThreadsInPool;
private BlockingQueue<String> queue;
public ThreadDeadlockDemo(int numThreads)
{
numThreadsInPool = numThreads;
executor = Executors.newFixedThreadPool(numThreads);
pool = new ExecutorCompletionService<String>(executor);
schedulerWorker = new HttpSchedulerWorker();
responseWorkerThread = new Thread(schedulerWorker);
responseWorkerThread.start();
queue = new LinkedBlockingQueue<String>();
new Thread(this).start();
}
public ThreadDeadlockDemo()
{
numThreadsInPool = 1;
executor = Executors.newFixedThreadPool(1);
pool = new ExecutorCompletionService<String>(executor);
schedulerWorker = new HttpSchedulerWorker();
responseWorkerThread = new Thread(schedulerWorker);
responseWorkerThread.start();
queue = new LinkedBlockingQueue<String>();
new Thread(this).start();
}
public void setThreadCount(int numThreads)
{
executor = Executors.newFixedThreadPool(numThreads);
pool = new ExecutorCompletionService<String>(executor);
numThreadsInPool = numThreads;
}
public void add(String info) {
queue.add(info);
}
@Override
public void run() {
// TODO Auto-generated method stub
while(shouldRun)
{
try {
String info = queue.take();
Callable<String> worker = new WorkerThread(info);
System.out.println("submitting to pooler: " + info);
pool.submit(worker);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* Inner class of proxy is a worker thread blocks until the pool has transactions complete as soon as they
* are complete it will send them to server for completion.
* @author Steve
*
*/
class HttpSchedulerWorker implements Runnable{
public void run() {
// TODO Auto-generated method stub
while(true)
{
String vulnInfo = null;
try {
Future<String> tmp = pool.take();
// Future<VulnInfo> tmp = pool.poll();
if(tmp != null)
vulnInfo = tmp.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(vulnInfo != null)
{
System.out.println("info was taken from pool completed: " + vulnInfo);
}
}
}
}
}
WorkerClass:这是添加到执行器池并返回的线程工作者,但在某些情况下,从未在ThreadlockDemos ExecutorCompletionService池中收到通知
import java.util.concurrent.Callable;
public class WorkerThread implements Callable<String>{
String info;
WorkerThread(String info)
{
this.info = info;
}
//@Override
public String call() throws Exception {
System.out.println("sending vuln info: " + info);
return info;
}
}
下面是我的测试类,它只是将项目添加到队列中。这是从我的控制台打印出来的一张看起来失败了的照片。Its添加到队列中对其起作用并返回值。但是,这种想法从来就不是什么想法,为什么?它有时会工作,有时会失败,这让我很难看出哪里出了问题。我很想说它在java中的bug,但我环顾四周,没有发现这些类有任何问题
public class HttpSchedulerThreadedUnitTest {
ThreadDeadlockDemo scheduler;
public HttpSchedulerThreadedUnitTest(){
setupScheduler();
for(int i=0; i < 5;i++)
{
scheduler.add(i+"");
}
}
private void setupScheduler()
{
scheduler = new ThreadDeadlockDemo();
scheduler.setThreadCount(1);
}
public static void main(String[] args)
{
new HttpSchedulerThreadedUnitTest();
}
}
控制台打印:当WorkerThread完成时,它从不从池中取出
正在提交到池程序:0
提交给pooler:1
提交给pooler:2
正在发送vuln信息:0
提交给pooler:3
正在发送vuln信息:1
提交给pooler:4
正在发送vuln信息:2
正在发送vuln信息:3
正在发送vuln信息:4
控制台打印:它实际上正在从池中获取itenms!
正在提交到池程序:0
提交给pooler:1
提交给pooler:2
提交给pooler:3
提交给pooler:4
正在发送vuln信息:0
已完成从池中获取信息:0
正在发送vuln信息:1
已完成从池中获取信息:1
正在发送vuln信息:2
从池中获取的信息已完成:2
正在发送vuln信息:3
从池中获取的信息已完成:3
正在发送vuln信息:4
从池中获取信息已完成:4这是大量代码。如果您可以通过删除http相关部分等来减少它,那就太好了。我也不确定返回ExecutorCompletionService之后是什么意思。take从来没有看到过它,所以从来没有看到返回更多项目的阻塞 您可以在线程锁定时进行线程转储,并查看哪个线程在代码的哪个点被锁定 同时,我确实看到一些代码看起来是错误的
while(requestQueue.isEmpty()){
try {
synchronized(this)
{
wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
这里,您正在一个可运行对象上进行同步。这几乎总是错误的,因为可运行对象通常不会被多个线程访问。此外,您正在测试synchronized语句之外的条件。通常,您使用wait的方式如下:
synchronized(lock){
while(!condition){
wait();
}
}
但是,我没有看到任何在runnable上调用notify的代码。这可能会导致程序挂起。基本上你在等待什么,但是没有人叫醒你,所以你无限期地等待。这是否是您面临的问题的原因,可以通过查看发生这种情况时的线程转储来轻松确定
若您使用的是队列,最好的建议是对请求队列使用阻塞队列。这样,您就不必完全执行等待/通知业务 我清理了代码,使其能够运行,以测试不依赖项。我让它添加并返回一个字符串。我按照你提到的做了,并添加了一个阻塞队列。这有助于清理代码,但仍然存在相同的死锁问题。你知道这段代码中的死锁是什么吗?看起来很简单,我没有看到任何错误的实现?我忘了提到我做了线程转储,但无法从提供的数据中确定任何内容。也许其他人可以理解它:线程转储:ame:pool-2-Thread-1状态:WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5fcf29阻止总数:1等待总数:1堆栈跟踪:sun.misc.Unsafe.parknown方法java.util.concurrent.locks.LockSupport.parknown源java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitUnknown Source java.util.concurrent.LinkedBlockingQueue.takeUnknown Source java.util.concurrent.ThreadPoolExecutor.Gettaskunown Source java.util.concurrent.ThreadPoolExecutor$Worker.runUnknown Source java.lang.Thread.runUnknown Source由于exdcutor和池在启动线程后已处于阻塞状态。把事情搞砸了。。public void setThreadCountint numThreads{executor=Executors.newFixedThreadPoolnumThreads;pool=new ExecutorCompletionServiceexecutor;numThreadsInPool =numThreads;}