Java 使用BlockingQueue和多线程。所有线程都卡在等待中

Java 使用BlockingQueue和多线程。所有线程都卡在等待中,java,multithreading,concurrency,thread-safety,blockingqueue,Java,Multithreading,Concurrency,Thread Safety,Blockingqueue,我正在创建一个系统,该系统将有多个套件部署,每个部署将有一个测试套件队列。由于我希望测试套件在各自的套件部署上并发运行,因此需要向代码中添加并发性。我已经创建了我正在使用的代码的简化版本,但是当我试图关闭它时,并发部分不起作用 调用Runner.stopEverything()时,结果是队列清空,等待线程完成,但即使测试全部完成,等待也永远不会完成,即使使用notifyAll()。其结果是,这一过程永远不会结束。我在调试模式下查看它,结果是所有3个线程都显示为等待 主要内容: public st

我正在创建一个系统,该系统将有多个套件部署,每个部署将有一个测试套件队列。由于我希望测试套件在各自的套件部署上并发运行,因此需要向代码中添加并发性。我已经创建了我正在使用的代码的简化版本,但是当我试图关闭它时,并发部分不起作用

调用Runner.stopEverything()时,结果是队列清空,等待线程完成,但即使测试全部完成,等待也永远不会完成,即使使用notifyAll()。其结果是,这一过程永远不会结束。我在调试模式下查看它,结果是所有3个线程都显示为等待

主要内容:

public static void main(String args[]) throws Exception {
  Runner.queueTestSuites("SD1", Arrays.asList("A", "B", "C"));
  Runner.queueTestSuites("SD2", Arrays.asList("D", "E", "F"));
  Runner.queueTestSuites("SD3", Arrays.asList("G", "H", "I"));

  Thread.sleep(5000);

  System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~");
  Runner.stopEverything();
}
跑步者:

public class Runner {
  private static Map<String, TestQueue> runnerQueueMap = new ConcurrentHashMap<>();

  public synchronized static void queueTestSuites(String suiteDeployment, List<String> testSuiteQueueAsJSON) throws Exception {
    TestQueue queue;
    if(runnerQueueMap.containsKey(suiteDeployment)) {
      queue = runnerQueueMap.get(suiteDeployment);
    } else {
      queue = new TestQueue(suiteDeployment);
    }
    for (int i = 0; i < testSuiteQueueAsJSON.size(); i++) {
      String name = testSuiteQueueAsJSON.get(i);
      queue.addToQueue(name);
    }
    runnerQueueMap.put(suiteDeployment,queue);
  }

  public synchronized static void stopEverything() throws InterruptedException {
    for (String s : runnerQueueMap.keySet()) {
      TestQueue q = runnerQueueMap.get(s);
      q.saveAndClearQueue();
    }

    for (String s : runnerQueueMap.keySet()) {
      TestQueue q = runnerQueueMap.get(s);
      q.waitForThread();
    }

    System.out.println("All done at " + new Date());
  }
}

在使用者的run方法中,有一个对queue.take()的阻塞调用,这意味着它将阻塞,直到队列中有一个项为止。队列中的元素最终用完,所有线程都被队列阻塞。take()调用将等待更多元素可供处理

尽管您的调用处于while循环中,它会检查线程是否被中断,但实际上您从未中断线程,因此它从未进入while循环求值&在对queue.take()的调用中被阻塞

所以,当线程在阻塞队列中等待输入变得可用时,它们会一直等待

另外,saveAndClear方法必须锁定正确的对象,即队列本身,如下所示:

public void saveAndClearQueue() {
    List<String> suiteNames = new ArrayList<String>();
    synchronized (queue) {
        for (String suite : queue) {
            suiteNames.add(suite);
        }
        queue.clear();
    }
    System.out.println("Saved(not executed) : "+suiteNames);
}
public void waitForThread() {
    synchronized (consumerThread) {
        while (consumer.running.get()) {
            try {
                consumerThread.wait(100);
            } catch (InterruptedException e) {
                break;
            }
        }
    }

    if (!consumer.running.get()) {
        consumerThread.interrupt();
    }

    System.out.println("Thread complete at " + new Date());
}
if(consumer.running.get()){synchronized(consumerThread){
-如果
consumer.running
变为false,然后当主线程正好在
if
语句中(但尚未调用
wait
)时,测试线程调用
notifyAll
,会发生什么?
public void saveAndClearQueue() {
    List<String> suiteNames = new ArrayList<String>();
    synchronized (queue) {
        for (String suite : queue) {
            suiteNames.add(suite);
        }
        queue.clear();
    }
    System.out.println("Saved(not executed) : "+suiteNames);
}
public void waitForThread() {
    synchronized (consumerThread) {
        while (consumer.running.get()) {
            try {
                consumerThread.wait(100);
            } catch (InterruptedException e) {
                break;
            }
        }
    }

    if (!consumer.running.get()) {
        consumerThread.interrupt();
    }

    System.out.println("Thread complete at " + new Date());
}