Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ExecutorCompletionService不接受Callable返回的项?_Java_Multithreading_Concurrency - Fatal编程技术网

Java ExecutorCompletionService不接受Callable返回的项?

Java ExecutorCompletionService不接受Callable返回的项?,java,multithreading,concurrency,Java,Multithreading,Concurrency,我在ExecutorCompletionService有奇怪的行为。该项将添加到ExecutorCompletionService.submit fine。然后它得到处理,并由先前提交的可调用工作线程返回。在返回之后,ExecutorCompletionService.take从未看到它,因此从未看到返回更多项目的阻塞?我真的不知道发生了什么事。我已经创建了打印行,可以看到它完成了可调用的工作线程。一旦发生这种情况,ExecutorCompletionService.take就应该准备好接收,但

我在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;}