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();// 释放锁
		}
	}
}

 

 

多线程编程入门(14):Condition实现线程通信

1 Condition的功能类似在传统线程技术中的Object.wait和Object.notify的功能. package cn.itcast.heima2; import java.util....
  • u010689306
  • u010689306
  • 2016年08月02日 22:45
  • 271

线程通信---使用Condition控制线程通信

  • confirmAname
  • confirmAname
  • 2014年04月01日 17:53
  • 280

使用Condition控制线程通信

一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A->B->C ...
  • lwj0310
  • lwj0310
  • 2014年04月25日 11:03
  • 308

Condition线程通信

那么引入本篇的主角,Condition,Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现...
  • u012129558
  • u012129558
  • 2016年05月14日 16:24
  • 166

使用Condition控制线程通信:

使用Condition控制线程通信: (1)如果不使用synchronized关键字保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能使用wait() not...
  • zlz18225318697
  • zlz18225318697
  • 2016年09月21日 14:03
  • 144

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

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

java使用condition进行线程通信

java使用condition进行线程通信
  • qingqingzijinxin
  • qingqingzijinxin
  • 2017年05月31日 14:54
  • 120

使用Condition类控制线程通信

在开发程序中,当我们常常需要并发处理一下程序来提高运行效率,在保证线程安茜以及执行线程通信情况下,相对于传统JavaObject的线程通信来说,Condition类来控制线程通信可以为多个线程建立不同...
  • xuguoli_beyondboy
  • xuguoli_beyondboy
  • 2015年03月15日 15:54
  • 398

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

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

Condition 控制线程通信

Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock 可能与多个Condi...
  • lengjinghk
  • lengjinghk
  • 2017年10月01日 21:33
  • 899
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Condition使用---线程通信
举报原因:
原因补充:

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