java多线程:结合多线程交替打印10次abc实例,对wait/notify使用的彻底理解

接上篇:http://blog.csdn.net/wabiaozia/article/details/79429585

有个朋友看点击打开链接 里的三个线程“A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。” 这个问题的代码,有点不太理解,让我给看下。不理解的原因也很简单,就是对wait和notify理解不深,遇到复杂点的场景会迷糊。对于并发相关的东西,非常推荐书并发编程实战(童云兰译)。这篇博客纯粹是为了直观理解而写,所以讲解时用词不准确,如果是想看一些概念的精确定义,建议看书,不要看这篇。

 

/**
 * wait用法
 * @author DreamSea 
 * @time 2015.3.9 
 */
package com.multithread.wait;
public class MyThreadPrinter2 implements Runnable {   	  
    private String name;   
    private Object prev;   
    private Object self;     
    private MyThreadPrinter2(String name, Object prev, Object self) {   
        this.name = name;   
        this.prev = prev;   
        this.self = self;   
    }     
    @Override  
    public void run() {   
        int count = 10;   
        while (count > 0) {   
            synchronized (prev) {   // 1 代码1 处
                synchronized (self) {   // 2 代码2 处
                    System.out.print(name);   
                    count--;                      
                    self.notify();   // 3 代码3处
                }   
                try {   
                    prev.wait();   // 4 代码4处
                } catch (InterruptedException e) {   
                    e.printStackTrace();   
                }   
            }     
        }   
    }   
  
    public static void main(String[] args) throws Exception {   
        Object a = new Object();   
        Object b = new Object();   
        Object c = new Object();   
        MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);   
        MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);   
        MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);             
           
        new Thread(pa).start();
        Thread.sleep(100);  //确保按顺序A、B、C执行
        new Thread(pb).start();
        Thread.sleep(100);  
        new Thread(pc).start();   
        Thread.sleep(100);  
        }   
}  

正文:

一些概念:

1 wait会释放锁,并使当前线程休眠。

2 有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁。

结合代码理解:

问1: "wait会释放锁,并使当前线程休眠"的理解

第一次A线程先执行,new Thread(pa).start()。在代码中1和2处分别拥有prev(c锁)和self(a锁)。

对于初学者来说在A线程过程中,代码中4处要理解到哪些点呢?

第一点,wait会释放锁,释放谁的锁?因为是prev.wait(),所以释放的是prev锁,即c锁。第二点,使线程休眠,哪个线程休眠?是不是说因为是prev.wait(),所以休眠的是prev(c锁)对应的c线程呢?不是,这里的休眠是当前运行的线程休眠,即A线程休眠,而不是c线程休眠。第三点,如何唤醒A线程呢,使用a.notify还是c.notify是不是说当前线程休眠了,用当前线程唤醒(a.notify)就行了?不是,前面用的是c.wait (即代码中的prev.wait,执行时参数prev代指的就是c)使线程A休眠。所以这里仍然需要c.notify唤醒线程A。

{2018.5.27补充:

最近想系统的看下并发编程相关的东西,更进一步的研究下边边角角的小知识。看并发编程实战的时候,不知是中文翻译的问题,还是图书作者doug lea段位太高的原因,有些段落让人读了不明所以。于是就结合了其他并发书籍交叉阅读。在翻"java并发编程的艺术"时,扫了一眼“等待/通知机制”章节,发现介绍的还不错,而且也正好和我的这篇博客主题契合,这里就摘要一些。转载自链接:http://blog.csdn.net/wabiaozia/article/details/79534560

等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类java.lang.Object上
等待/通知机制,是指一个
线程A调用对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。

}

问2: notify()调用后,会马上就释放对象锁

下文中的代码3处,notify()调用后并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁。

问3:小结下A线程的执行流程

执行代码1和2处,分别是c和a锁,这点很好理解。代码3处释放a锁。代码4处,释放c锁,同时休眠A线程,下次需要c.notify() 才能唤醒A线程。

问4:还有其他解法吗?转载表明链接:http://blog.csdn.net/wabiaozia/article/details/79534560

有lock锁,ReentrantLock结合Condition,信号量Semaphore等。我博客所有文章链接:http://blog.csdn.net/wabiaozia

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菠萝科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值