java多线程 - 线程通信

当线程在系统内运行时,程序通常无法准确控制线程的轮换执行,但是可以通过一些机制来保证线程协调运行。

由同步监视器对象协调线程

实现这种功能可以借助于Object类提供的wait()、notify()、notifyAll()三个方法(注意,这三个方法属于Object类,不属于Thread类)。这三个方法必须由同步监视器来调用,可以分为两种情况:

  • 对于同步方法,同步监视器默认是当前实例(this),所以可以在同步方法中直接调用这三个方法;
  • 对于同步代码块,同步监视器是synchronized后括号里的对象,必须使用该对象调用这三个方法。

介绍下这三个方法:

wait():导致当前线程等待(由运行进入阻塞),直到其他线程调用该同步监视器的notify()或notifyAll()方法来唤醒该线程。wait()方法会使当前线程释放对同步监视器的锁定;

notify():唤醒(由阻塞进入就绪)在同步监视器上等待的一个线程。如果多个线程都此同步监视器上等待,则会任意唤醒其中一个线程。被唤醒的线程不能立即执行,需要当前线程释放对同步监视器的锁定后才可以;

notifyAll:唤醒在同步监视器上等待的所有线程。同样被唤醒的线程不能立即执行,需要当前线程释放对同步监视器的锁定后才可以获得执行的机会。

使用条件变量协调控制线程

当线程使用同步锁来实现线程同步时,系统中不存在隐式的同步监视对象,也就不能使用wait()、notify()、notifyAll()来协调线程。

当使用Lock对象保证线程同步时,Java提供了Condition类来协调线程通信。Condition实例实质上被绑定在Lock对象上,要获得特定Lock的Condition实例,使用该对象的newCondition()方法即可。

Condition提供了await()、signal()、signalAll()来实现线程协调。这三个方法分别对应同步监视器对象的wait()、notify()、notifyAll()方法,只不过调用者不同罢了。

使用管道流进行线程通信

管道流分为三大类:管道字节流(PipedInputStream和PipedOutputStream)、管道字符流(PipedReader和PipedWriter)和新IO管道(Pipe.SinkChannel和Pipe.SourceChannel)。

使用管道流进行线程通信可按如下步骤进行:

  1. 使用new关键字分别创建管道输入流和管道输出流;
  2. 使用管道输入流或管道输出流的connect方法把两个输入流和输出流连接起来;
  3. 将管道输入流、管道输出流分别传入两个线程;
  4. 两个线程分别依赖各自的管道输入流、管道输出流进行通信。

尽量少使用管道流进行通信,最好的方式还是使用线程共享数据进行通信。

posted @ 2014-12-01 22:19  robin·张  阅读(262)  评论(0编辑  收藏  举报