Condition使用---线程通信

原创 2013年12月04日 10:25:42

线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我可以定义多个Condition,每个condition控制线程的一条执行通路。传统方式只能是一路等待

 

下面这个例子:启动三个线程分别运行sub1、sub2、sub3,要求是运行完sub1之后再运行完sub2,运行完sub2之后运行sub3,运行完sub3之后重新运行sub1,重复50次。

package hb.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionCommunication {

	public static void main(String[] args) {

		final Business business = new Business();

		new Thread(new Runnable() {

			public void run() {
				for (int i = 0; i < 50; i++) {
					business.sub1(i);
				}
			}

		}).start();

		new Thread(new Runnable() {

			public void run() {
				for (int i = 0; i < 50; i++) {
					business.sub2(i);
				}
			}

		}).start();

		new Thread(new Runnable() {

			public void run() {
				for (int i = 0; i < 50; i++) {
					business.sub3(i);
				}
			}

		}).start();
	}

	static class Business {
		private int shouldSub = 1;
		private Lock lock = new ReentrantLock();

		Condition condition1 = lock.newCondition();
		Condition condition2 = lock.newCondition();
		Condition condition3 = lock.newCondition();

		public void sub1(int i) {
			try {
				lock.lock();
				while (shouldSub != 1) {
					try {
						condition1.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 1; j <= 10; j++) {
					System.out.println("sub1 thread sequence is " + j + " loop of " + i);
				}
				shouldSub = 2;
				condition2.signal();
			} finally {
				lock.unlock();
			}
		}

		public void sub2(int i) {
			try {
				lock.lock();
				while (shouldSub != 2) {
					try {
						condition2.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				for (int j = 1; j <= 10; j++) {
					System.out.println("sub2 thread sequence is " + j + " loop of " + i);
				}
				shouldSub = 3;
				condition3.signal();
			} finally {
				lock.unlock();
			}
		}

		public void sub3(int i) {
			try {
				lock.lock();
				while (shouldSub != 3) {
					try {
						condition3.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				for (int j = 1; j <= 10; j++) {
					System.out.println("sub3 thread sequence is " + j + " loop of " + i);
				}
				shouldSub = 1;
				condition1.signal();
			} finally {
				lock.unlock();
			}
		}

	}
}

 API说明:

await() : 造成当前线程在接到信号或被中断之前一直处于等待状态。

signal() : 唤醒一个等待线程。

 


 

 我们可以先分析下Java5 Api中的缓冲队列的实现:

假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存put 线程和take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个Condition 实例来做到这一点。

class BoundedBuffer {
	final Lock lock = new ReentrantLock();// 实例化一个锁对象
	final Condition notFull = lock.newCondition(); // 实例化两个condition
	final Condition notEmpty = lock.newCondition();

	final Object[] items = new Object[100];// 初始化一个长度为100的队列
	int putptr, takeptr, count;

	public void put(Object x) throws InterruptedException {
		lock.lock();// 获取锁
		try {
			while (count == items.length)
				notFull.await();// 当计数器count等于队列的长度时,不能在插入,因此等待
			items[putptr] = x; // 将对象放入putptr索引处
			if (++putptr == items.length)
				putptr = 0;// 当索引长度等于队列长度时,将putptr置为0
			// 原因是,不能越界插入
			++count;// 没放入一个对象就将计数器加1
			notEmpty.signal();// 一旦插入就唤醒取数据线程
		} finally {
			lock.unlock();// 最后释放锁
		}
	}

	public Object take() throws InterruptedException {
		lock.lock();// 获取锁
		try {
			while (count == 0)
				// 如果计数器等于0那么等待
				notEmpty.await();
			Object x = items[takeptr]; // 取得takeptr索引处对象
			if (++takeptr == items.length)
				takeptr = 0;// 当takeptr达到队列长度时,从零开始取
			--count;// 每取一个讲计数器减1
			notFull.signal();// 枚取走一个就唤醒存线程
			return x;
		} finally {
			lock.unlock();// 释放锁
		}
	}
}

 

 

多线程 : 使用Lock 和 Condition 实现线程间互斥与通信

package thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock...

java学习——如何实现线程之间的通信 ,Condition 的使用

package com.hujl.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.l...

JAVA5多线程---Condition使用---线程通信 --wait及notify方法

JAVA5多线程---Condition使用---线程通信   线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支...

java使用condition进行线程通信

java使用condition进行线程通信

JAVA多线程---Condition使用---线程通信

线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我可以定义多个Condition,每个conditio...

JAVA5多线程---Condition使用---线程通信

线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我可以定义多个Condition,每个conditio...

Condition 条件变量,线程通信更高效的方式

条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以...

Java 多线程(三)线程间的通信jdk1.5中Lock,Condition---生产者消费者为例

1.使用Lock和Condition的意义     JDK1.5中提供了多线程升级的解决方案。     1.将同步synchronized替换成现实Lock操作。     2.将Object中的wai...

Lock和Condition实现线程通信(附阻塞队列的实例)

第一种情况:就使用单个Condition对象实现通信,方式同wait()和notify()   condition是await()和signal(),其中condition对象是通过lock.get...
  • com360
  • com360
  • 2011年09月21日 17:22
  • 3908

[疯狂Java]多线程:线程通信(监控器信号、Condition信号、阻塞队列)

1. 线程通信的概念:     1) 即线程之间以信号的方式(发送/接收信号)相互协调,协调的内容是调度; !!通常调度都是有调度器完成的,程序员无法插手(完全是透明的),但不过在有些情况下还是有人为...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Condition使用---线程通信
举报原因:
原因补充:

(最多只允许输入30个字)