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