关于Java多线程遇到的问题.
阿神
阿神 2017-04-17 17:31:59
[Java讨论组]

1.最近在学习Java多线程,看到视频中要实现一个类似闹钟和小明的情景, 要求闹钟响,小明关闹钟, 三秒后闹钟再响,小明再关, 重复10次程序结束. 不知道为什么我的程序小明只能输出一次.

public class Test {
    public static void main(String[] args) {
        Clock ck = new Clock();
        new XiaoMing(ck);
    }
}


public class Clock implements Runnable{
    public Boolean isAlarm;
    public Boolean shutdown;

    public Clock() {
        isAlarm = false;
        shutdown = false;
        new Thread(this).start();
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            isAlarm = true;
            System.out.println("Get up * 3 !");
            synchronized (this) {
                notifyAll();
                try {
                    wait(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        shutdown = true;
    }
}


public class XiaoMing implements Runnable{
    private Clock clk;

    public XiaoMing(Clock clk) {
        this.clk = clk;
        new Thread(this).start();
    }

    @Override
    public void run() {
        while(true) {
            if (clk.isAlarm) {
                System.out.println("Woshixiaoming!");
                clk.isAlarm = false;
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            else{
                if(clk.shutdown)    break;
            }
        }
    }
}

输出结果如下

Get up * 3 !
Woshixiaoming!
Get up * 3 !
Get up * 3 !
...(10 次 Getup, 之后程序停在那里)
阿神
阿神

闭关修行中......

全部回复(2)
迷茫

这是因为你没有理解到wait(),notify(),notifyAll()这三个方法的真正作用,它们不是控制的所有线程,而是所对象的线程。
也就是说,XiaoMing 的同步锁里调用的 wait() 方法阻塞的是 XiaoMing 这个线程;Clock 的同步锁唤醒的是 Clock 类的对象的线程,所以 XiaoMing 的对象的线程就一直阻塞下去了
可以修改 XiaoMing 类run()方法的同步锁

@Override
    public void run() {
        while(true) {
            if (clk.isAlarm) {
                System.out.println("Woshixiaoming!");
                clk.isAlarm = false;
                synchronized (this.clk) {
                    try {
                        this.clk.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            else{
                if(clk.shutdown)    break;
            }
        }
    }

这样 XiaoMing 的线程会因为clk域被阻塞,直到Clock的线程调用notifyAll()

黄舟

clk.isAlarm在第一次xiaomin打印后之后为false,后面没在再变回true,所以在clock类里要重设回true

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号