线程间的同步与通信

本文介绍了Java中实现线程间通信的wait(), wait(long timeout), wait(long timeout, int nanos), notify(), notifyAll()五种方法,详细解析了锁池与等待池的概念,并探讨了notify()与notifyAll()的区别。通过一个实例展示了如何让三个线程轮流打印ABC,以此理解线程同步的重要性。" 78364421,1501275,Drupal8内容实体基类详解与设计模式分析,"['Drupal8源码分析', '内容实体', '编程设计模式']
摘要由CSDN通过智能技术生成

线程间通信的方法

        在Java中,我们可以使用
                                            wait()
                                            wait(long timeout)
                                            wait(long timeout,int naos)
                                            notify()
                                            notifyAll()

        这5个方法来实现线程间的通信。

        其中wait()方法的作用是,阻塞当前线程(阻塞的原因常常是一些必要的条件还没有满足),一个线程在调用wait()方法后,会释放当前的锁对象,不再参与竞争,直到其他线程调用了这个锁的notifyAll()、或notify()方法,这个被阻塞的线程才会有可能继续执行

        注意,上面说的是有可能继续执行,这是为什么呢?这是因为,当那些被notifyAll()唤醒的线程,同时去抢一把锁时,只有一个线程可以成功抢到,此时成功抢到锁的线程才能继续执行,而那些没有抢到锁的线程,则继续是阻塞状态。

        notify()、notifyAll()方法的作用是,唤醒那些调用了wait()方法的线程。notify()是唤醒其中一个,notifyAll()是全部唤醒。

        上述的5个方法,都是定义在Object类中。

锁池与等待池

        锁池:假设线程A已经拥有了某个对象的monitor锁,而其他的线程调用这个对象的synchronized方法(或者synchronized代码块),由于这些线程在进入已经被对象的synchronized方法之前必须先获得该对象的monitor的拥有权,但是该对象的锁目前正在被线程A拥有,所以这些想要获取该对象monitor拥有权的线程就进入到了该对象的锁池中。
        等待池: 假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的monitor,进入到该对象的等待池中。

        我们通过一个很简单的伪代码再来看一看锁池:

class Handler extends Thread{
   
	Object o = new Object
	public void run(){
   
		sychronized(o){
   
			...
		}
	}
}

        假设现在有两个线程,分别为A、B。假设线程A先执行,那么线程A会执行到synchronized代码块时,首先获取对象o的monitor,此时,对象o的monitor的拥有者为线程A,然后线程A进入synchronized代码块执行。此时,线程B也要执行synchronized代码块里的内容,它发现对象o的monitor已经被占用了,此时,线程B就会进入到对象o的锁池中等待线程A释放掉对象o的monitor的使用权。

notify()、notifyAll()区别

        notify()、notifyAll()的区别在于:

                notify唤醒的是对象等待池中的一个线程,这个线程进入Blocked状态,开始抢锁(注意,被唤醒的线程进入BLOCKED状态,而不是RUNNABLE状态),当这个线程执行完释放锁的时候,即使没有其他线程占用锁,其它处于wait状态的等待池中的线程也会继续等待被唤醒。即处于对象等待池的线程,不会主动去抢锁。

                调用notifyAll()后,所有处于对象等待池中的线程都会被唤醒,当这个对象的锁被释放掉后,这些原处于等待池中的线程都会去抢锁。抢到锁的线程去执行,没有抢到锁的线程进入BLOCKED状态。

三个线程轮流打印ABC

        我们通过一个例子,去体会线程间的通信。我们使用三个线程,使这三个线程轮流打印A、B、C共10次。

class ABCHandler{
   
    private Object o = new Object();
    private
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值