Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.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 等待的线程永远不会醒来_Java_Multithreading_Wait_Notify - Fatal编程技术网

Java 等待的线程永远不会醒来

Java 等待的线程永远不会醒来,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我有一个有两个线程的线程管理器。一个用于gui相关请求,另一个用于度量相关请求。正在运行并检查其请求队列,如果有,则正在处理该请求。您可以随时使用静态ThreadManager.addGuiRequest(eGuiRequest)和ThreadManager.addMeasRequest(eMeasRequest)方法添加请求。现在这两个都需要初始化,这是通过向相应的队列添加INIT请求来完成的。但是度量的初始化取决于gui已经初始化的事实。我尝试使用wait()/notify()解决此问题,但

我有一个有两个线程的线程管理器。一个用于gui相关请求,另一个用于度量相关请求。正在运行并检查其请求队列,如果有,则正在处理该请求。您可以随时使用静态
ThreadManager.addGuiRequest(eGuiRequest)
ThreadManager.addMeasRequest(eMeasRequest)
方法添加请求。现在这两个都需要初始化,这是通过向相应的队列添加
INIT
请求来完成的。但是度量的初始化取决于gui已经初始化的事实。我尝试使用
wait()/notify()
解决此问题,但无法使其正常工作

这是一个SSCCE。在启动时,两个队列都添加了INIT请求,然后启动。测量初始化检测到gui尚未初始化,并执行
wait()
。gui初始化(通过睡眠5s模拟)。这一切都很好

gui初始化后,它尝试唤醒测量线程,但测量线程没有唤醒。。。我的
wait()/notify()
代码基于。这里出了什么问题

import java.util.LinkedList;
import java.util.NoSuchElementException;

public class ThreadManager {    
    public static void main(String[] args) {
        new ThreadManager();
        ThreadManager.addMeasRequest(eMeasRequest.OTHER_STUFF);
    }

    public enum eGuiRequest { INIT, OTHER_STUFF; }
    public enum eMeasRequest { INIT, OTHER_STUFF; }

    private static LinkedList<eGuiRequest> guiQueue = new LinkedList<eGuiRequest>();
    private static LinkedList<eMeasRequest> measQueue = new LinkedList<eMeasRequest>();
    private static Thread guiThread, measThread;
    protected boolean initialized = false;

    public ThreadManager() {
        final int waitMs = 200;    
        guiThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        if (guiQueue.isEmpty()) sleepMs(waitMs);
                        else {
                            eGuiRequest req = guiQueue.getFirst();
                            processGuiRequest(req);
                            guiQueue.removeFirst();
                        }
                    } catch (NoSuchElementException e) {}
                }
            }

            private void processGuiRequest(eGuiRequest req) {
                System.out.println("T: " + "Processing Gui request: " + req);
                switch (req) {
                case INIT:
                    // do some initializiation here - replaced by a wait:
                    sleepMs(5000);
                    System.out.println("I: " + "guiThread finished, waking up measThread");
                    synchronized (measThread) {
                        initialized = true;
                        measThread.notify();
                    }
                    break;
                case OTHER_STUFF:
                    // do other stuff
                    break;
                }
            }
        });
        measThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        if (measQueue.isEmpty()) sleepMs(waitMs);
                        else {
                            eMeasRequest req = measQueue.getFirst();
                            processMeasurementRequest(req);
                            measQueue.removeFirst();
                        }
                    } catch (NoSuchElementException e) {}
                }
            }

            private void processMeasurementRequest(eMeasRequest req) {
                if (req == eMeasRequest.INIT) { // if init, wait until GUI is initialized
                    synchronized (this) {
                        while (!initialized) {
                            System.out.println("I: " + "measThread waits for guiThread to finish initializiation");
                            try {
                                wait();
                            } catch (Exception e) {}
                            System.out.println("I: " + "measThread awakes");
                        }
                    }
                }
                System.out.println("T: " + "Processing Measurement request: " + req);
                // process request here:
                sleepMs(5000);
            }
        });

        addGuiRequest(eGuiRequest.INIT);
        addMeasRequest(eMeasRequest.INIT);

        guiThread.start();
        measThread.start();
    }

    public static void sleepMs(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException ee) {}
    }

    public static void addGuiRequest(eGuiRequest req) {
        guiQueue.add(req);
    }

    public static void addMeasRequest(eMeasRequest req) {
        measQueue.add(req);
    }
}
import java.util.LinkedList;
导入java.util.NoSuchElementException;
公共类线程管理器{
公共静态void main(字符串[]args){
新线程管理器();
ThreadManager.addMeasRequest(eMeasRequest.OTHER_STUFF);
}
公共枚举eGuiRequest{INIT,OTHER_STUFF;}
公共枚举请求{INIT,OTHER_STUFF;}
private static LinkedList guiQueue=new LinkedList();
private static LinkedList measquee=new LinkedList();
私有静态线程guiThread、measThread;
受保护的布尔值初始化=false;
公共线程管理器(){
最终整数waitMs=200;
guiThread=newthread(newrunnable()){
@凌驾
公开募捐{
while(true){
试一试{
if(guiQueue.isEmpty())sleepMs(waitMs);
否则{
eGuiRequest req=guiQueue.getFirst();
处理请求(req);
guiQueue.removeFirst();
}
}catch(NoSuchElementException e){}
}
}
专用无效处理请求(eGuiRequest req){
System.out.println(“T:+”处理Gui请求:“+req”);
开关(req){
案例初始:
//在此处进行初始化-替换为等待:
sleepMs(5000);
System.out.println(“I:“+”guiThread已完成,唤醒measThread”);
已同步(measThread){
初始化=真;
measThread.notify();
}
打破
案例其他内容:
//做其他事情
打破
}
}
});
measThread=新线程(new Runnable()){
@凌驾
公开募捐{
while(true){
试一试{
if(measQueue.isEmpty())sleepMs(waitMs);
否则{
eMeasRequest req=measQueue.getFirst();
过程测量请求(req);
measQueue.removeFirst();
}
}catch(NoSuchElementException e){}
}
}
私有void processMeasurementRequest(eMeasRequest-req){
if(req==eMeasRequest.INIT){//if INIT,等待GUI初始化
已同步(此){
而(!已初始化){
println(“I:“+”measThread等待guiThread完成初始化”);
试一试{
等待();
}捕获(例外e){}
System.out.println(“I:“+”measThread awakes”);
}
}
}
System.out.println(“T:“+”处理测量请求:“+req”);
//在此处处理请求:
sleepMs(5000);
}
});
addGuiRequest(eGuiRequest.INIT);
addMeasRequest(eMeasRequest.INIT);
guiThread.start();
measThread.start();
}
公共静态无效休眠ms(int ms){
试一试{
睡眠(ms);
}捕获(中断异常ee){}
}
公共静态void addGuiRequest(eGuiRequest req){
guiQueue.add(req);
}
公共静态无效addMeasRequest(eMeasRequest请求){
添加(要求的)测量值;
}
}

GUI线程在
measThread
上调用
notify()
(线程类型),而
processMeasurementRequest()
方法在
this
上调用
wait()
,这是
measThread
使用的可运行实例

我建议使用两个线程共享的特定对象来等待和通知:

private static final Object GUI_INITIALIZATION_MONITOR = new Object();
此外,我将使用BlockingQueue,而不是使用LinkedList并在请求之间休眠一段时间:这将允许消费线程在有请求时立即处理请求,并避免从休眠状态不必要的唤醒

此外,您可以使用初始化为1的倒计时闩锁,而不是低级的等待/通知。GUI线程将在锁存器初始化时
countDown()
锁存器,而测量线程将
wait()
锁存器,直到GUI线程调用
countDown()
。这将把复杂的同步和通知工作委托给一个更高级别、经过良好测试的对象private static final Object LOCK = new Object();
synchronized (LOCK) {
    while (!initialized) LOCK.wait();
}
quiQueue = Collections.synchronizedList(new LinkedList<eGuiRequest>());