线程的通信问题

概述

在现实中,我们有时需要线程之间的协作来处理问题,比如最经典的生产者消费者模式,生产者必须等到队列中有空间时才能继续往里面放货物,那么在等待的时间里,就需要释放对临界资源的占(队列),因为生产者不释放对队列的占用权,消费者就无法进行消费,那么生产者就会一直进行等待。对于消费者同样如此,这种互相通信的方式就是线程间的通信

实现线程通信的常用方式

实现线程间的通信最常见的以下两种方式
i>syncrhoized加锁object类下的wait(),notify(),notifyall()
ii>Reentrantlock加锁下的condition类下的await(),signal(),signalAll()
iii>使用阻塞队列控制线程通信
iv>通过管道实现线程间的通信,字节流,字符流

一、syncrhoized加锁,object类下的wait(),notify(),notifyall()

wait():导致当前线程等待,直到其他线程调用该同步监视器的notify,或者notifyAll()方法来唤醒该线程。该wait方法有三种形式。无时间参数的wait()一直等待,直到其他线程通知,带毫秒或微秒参数的wait()时间到了会自动苏醒。调用wait方法的当前线程会释放对该同步监视器的锁定。

notify():唤醒在此同步监视器上等待的单个线程。如果所有线程都在该同步监视器上等待,那么会选择唤醒其中的一个线程。注意:只有当前线程放弃对该同步监视器的锁定后(调用wait()方法),才会调用notify()方法。
notifyAll():唤醒在该同步监视器上等待的所有线程。也必须放弃对该同步监视器的锁定后才会调用此方法。

二、Reentrantlock加锁下的condition类下的await(),signal(),signalAll()

Condition实例被绑定在一个Lock对象上,要获得特定的Lock实例的Condition实例,调用Condition对象的newCondition方法即可。Condition类提供了如下的三个方法:
await():类似于wait()方法,导致当前线程等待,直到signal()或者signal()方法来唤醒该线程。
signal():唤醒在此lock对象上等待的单个线程,只有当前线程放弃对该lock对象的锁定后才能够唤醒该线程。
signalAll():唤醒在此lock对象上等待的所有线程。只有当前线程放弃对该lock对象的锁定后才能够唤醒该线程。

三、使用阻塞队列(BlockingQueue)控制线程通信

BlockingQueue具有一个特征当生产者往BlockingQueue中放入元素时,如果该队列已满,则引发阻塞。当消费者线程试图从BlockongQueue中拿出元素时,如果队列为空,则引发阻塞。通过两个线程交替操作,从而实现线程通信。
BlockingQueue提供如下的两个方法
put(E e):尝试把e元素放入BlockingQueue中,如果该队列元素已满,则引起阻塞
take():尝试从BlockingQueue中拿出元素,如果队列为空则引起阻塞。

四、通过管道实现线程间的通信

Java中有各种各样的输入、输出流(Stream),其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据。
一个线程发送数据到输出管道,另一个线程从输入管道读数据。

你可能感兴趣的:(多线程)