java并发编程(10)--Condition

1.如何得到Condition

在Lock中

 Condition newCondition()
          返回绑定到此 Lock 实例的新 Condition 实例。

2.使用Condition进行线程之间的通信 改进传统的线程之间同信代码

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

/**
 * 子线程循环10次 主线程循环100次 如此交替 50次
 * 
 * @author hao.su
 * 
 */
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.sub(i);
				}
			}
		}).start();
		for (int i = 0; i < 50; i++) {
			business.main(i);
		}
	}

	static class Business {
		Lock lock = new ReentrantLock();
		Condition condition = lock.newCondition();
		boolean bShouldSub = true;

		public  void sub(int i) {
			lock.lock();
			try {
				while (!bShouldSub) {// 用while防止未唤醒
					try {
						condition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j < 10; j++) {
					System.out.println("sub thread sequence of" + j
							+ ",loop of" + i);
				}
				
			} catch (Exception e) {
				
			}finally{
				lock.unlock();
			}
		}

		public  void main(int i) {
			lock.lock();
			try {
				while (bShouldSub) {
					try {
						condition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j < 100; j++) {
					System.out.println("main thread sequence of" + j
							+ ",loop of" + i);
				}
				bShouldSub = true;
				condition.signal();
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				lock.unlock();
			}
		}
	}
}
  在等待Condition时,允许发生虚假唤醒,这通常作为基础平台语义的让步,对于大多数应用程序,这带来的实际影响很小,因为Condition总应该在一个循环中等待,并测试正被等待的状态声明,某个实现可以随意移除可能的虚假唤醒,但建议应用程序程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。
  一个锁内部可以有多个Condition,即有多路等待通知,可以参考一下jdk中Lock和Condition实现可阻塞队列的案例

jdk帮助文档这样写道:

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

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

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }

但是ArrayBlockingQueue类提供了这项功能,因此没有必要去实现该项功能



4.实现功能,当A执行完毕后执行B之后执行C  c执行之后执行A 如此循环

package com.qunar.thread;

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

/**
 * 子线程循环10次 主线程循环100次 如此交替 50次
 * 
 * @author hao.su
 * 
 */
public class ThreeConditionCommunication {
	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.sub2(i);
				}
			}
		}).start();

		new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 50; i++) {
					business.sub3(i);
				}
			}
		}).start();
		for (int i = 0; i < 50; i++) {
			business.main(i);
		}
	}

	static class Business {
		Lock lock = new ReentrantLock();
		Condition condition1 = lock.newCondition();
		Condition condition2 = lock.newCondition();
		Condition condition3 = lock.newCondition();
		int iShouldSub = 1;

		public void sub2(int i) {
			lock.lock();
			try {
				while (iShouldSub != 2) {// 用while防止未唤醒
					try {
						condition2.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j < 10; j++) {
					System.out.println("sub2 thread sequence of" + j
							+ ",loop of" + i);
				}
				iShouldSub = 3;
				condition3.signal();
			} catch (Exception e) {

			} finally {
				lock.unlock();
			}
		}

		public void sub3(int i) {
			lock.lock();
			try {
				while (iShouldSub!=3) {// 用while防止未唤醒
					try {
						condition3.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j < 10; j++) {
					System.out.println("sub3 thread sequence of" + j
							+ ",loop of" + i);
				}
				iShouldSub = 1;
				condition1.signal();
			} catch (Exception e) {

			} finally {
				lock.unlock();
			}
		}

		public void main(int i) {
			lock.lock();
			try {
				while (iShouldSub!=1) {
					try {
						condition1.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				for (int j = 0; j < 100; j++) {
					System.out.println("main thread sequence of" + j
							+ ",loop of" + i);
				}
				iShouldSub = 2;
				condition2.signal();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
}



发布了93 篇原创文章 · 获赞 1 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章