当线程在系统内运行时,线程的调度具有一定的透明性,程序通常无法准确控制线程的轮换执行,但Java也提供了一些机制来保证线程协调运行。
1 传统的线程通信
可借助Object类提供的wait()、notify()和notifyAll()三个方法,注意这三个方法不属于Thread类,而是属于Object类,另外这三个方法必须由同步监视器(锁)对象来调用。对于同步方法,锁对象就是该类的默认实例this;对于同步代码块,锁对象就是synchronized后括号里的对象。
2 使用Condition控制线程通信
如果程序不适用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能使用wait()、notify()和notifyAll()方法进行线程通信了。
当使用Lock对象来保证同步时,Java提供了一个Condition类来保持协调,使用Condition可以让那些已经得到Lock对象却无法继续执行的线程释放Lock对象,Condition对象也可以唤醒其他处于等待的线程。
Condition实例被绑定在一个Lock对象上,要获得特定的Lock实例的Condition实例,调用Lock对象的newCondition()方法即可。Condition类提供了三个方法:await()、signal()和signalAll()。
3 使用阻塞队列控制线程通信
Java 5 提供了一个BlockingQueue接口,虽然BlockingQueue也是Queue的子接口,但它的主要用途并不是作为容器,而是作为线程同步的工具。
BlockingQueue具有一个特征:当生产者线程试图向BlockingQueue中放入元素时,如果该队列已满,则该线程被阻塞;当消费者线程试图从BlockingQueue中取出元素时,如果该队列已空,则该线程被阻塞。对应提供了两个支持阻塞的方法,put(E e)和take()。
BlockingQueue包含5个实现类:
(1)ArrayBlockingQueue是基于数组实现的BlockingQueue队列;
(2)LinkedBlockingQueue是基于链表实现的BlockingQueue对列;
(3)PriorityBlockingQueue是可以定制排序的非标准阻塞队列;
(4)SynchronousQueue:同步队列;
(5)DelayQueue底层是基于PriorityBlockingQueue实现。