如何使用多个线程的wait和notify协议

前端之家收集整理的这篇文章主要介绍了如何使用多个线程的wait和notify协议前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
具体来说,有人可以告诉我这段代码有什么问题.它应该启动线程,所以应该打印“输入线程…”5次,然后等到调用notifyAll().但是,它会随机打印“输入……”和“完成……”,并且仍在等待其他人.
public class ThreadTest implements Runnable {
    private int num;
    private static Object obj = new Object();
    ThreadTest(int n) {
        num=n;
    }
    @Override
    public void run() {
        synchronized (obj) {
            try {
                System.out.println("Entering thread "+num);
                obj.wait();
                System.out.println("Done Thread "+num);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
        }   
    }   

    public static void main(String[] args) {
        Runnable tc;
        Thread t;
        for(int i=0;i<5;i++) {
            tc = new ThreadTest(i);
            t = new Thread(tc);
            t.start();
        }
        synchronized (obj) {
            obj.notifyAll();
        }
    }
}

解决方法

你没有对方法调用做任何明显的错误,但是你有一个 race condition.

虽然在一个理想的世界中,主线程将在所有工作线程到达wait()调用后到达其synchronized块,但无法保证(您明确告诉虚拟机您不希望线程按顺序执行用主线程制作线程).可能发生(例如,如果您只有一个核心)线程调度程序决定立即阻止所有工作线程,它们开始允许主线程继续.可能由于高速缓存未命中而将工作线程切换出上下文.可能是一个工作线程阻塞I / O(print语句)并且主线程在其位置切换.

因此,如果主线程在所有工作线程到达wait()调用之前设法到达同步块,则那些尚未到达wait()调用的工作线程将无法按预期运行.由于当前设置不允许您控制此操作,因此必须添加对此的显式处理.您可以添加某种变量,当每个工作线程到达wait()并且主线程不调用notifyAll()直到此变量达到5,或者您可以使用主线程循环并重复调用notifyAll()时,会增加某种变量.以便工作线程在多个组中发布.

看一下java.util.concurrent包 – 有几个锁类提供比基本同步锁更强大的功能 – 一如既往,Java可以让你免于重新发明轮子. CountDownLatch似乎特别相关.

总之,并发很难.您必须设计以确保当线程在您不想要的订单中执行时,一切仍然有效,以及您希望的订单.

猜你在找的Java相关文章