多线程与并发-----条件阻塞Condition的应用

Condition

   1、 功能:

        其类似在传统线程技术中的 Object.wait() 和 Object.notify() 的功能,传统线程技术实现互斥只能是一个线程单独干,不能说这个线程干完了通知另一个线程来干,Condition就是解决这个问题:实现线程间的通信。比如CPU让小弟做事,小弟说我先歇着,并通知大哥,大哥开始做事。

    public interface Condition

    Condition 将 Object监视器方法(wait、notify和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待set(wait-set)。其中,Lock替代了 synchronized 方法和语句的使用,Condition替代了 Object 监视器方法的使用。

  2、 实质:

        实质上是被绑定到一个锁上。要为特定的 Lock 实例获得 Condition 实例,请使用 new 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.sub(i);
				}
				
			}
			
		}).start();
		
		for(int i=0;i<50;i++){
			business.main(i);
		}
	}
	
	static class Business{
		Lock lock=new ReentrantLock();
		Condition condition=lock.newCondition();
		private boolean bSholdSub=true;
		public void sub(int i){
			lock.lock();
			try{
				while(!bSholdSub){
					try {
						//this.wait();
						condition.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				for(int j=0;j<10;j++){
					System.out.println("sub thread sequence of"+j+",loop of"+i);
				}
				bSholdSub=false;
				condition.signal();
				//this.notify();//notify必须和synchronized一起用
			}finally{
				lock.unlock();
			}
			
		}
		
		public void main(int i){
			lock.lock();
			try{
				while(bSholdSub){
					try {
						//this.wait();
						condition.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				for(int j=0;j<10;j++){
					System.out.println("main thread sequence of"+j+",loop of"+i);
				}
				bSholdSub=true;
				//this.notify();
				condition.signal();
			}finally{
				lock.unlock();
			}
		}
	}

}

        运行结果为:

sub thread sequence of0,loop of0
sub thread sequence of1,loop of0
sub thread sequence of2,loop of0
sub thread sequence of3,loop of0
sub thread sequence of4,loop of0
sub thread sequence of5,loop of0
sub thread sequence of6,loop of0
sub thread sequence of7,loop of0
sub thread sequence of8,loop of0
sub thread sequence of9,loop of0
main thread sequence of0,loop of0
main thread sequence of1,loop of0
main thread sequence of2,loop of0
main thread sequence of3,loop of0
main thread sequence of4,loop of0
main thread sequence of5,loop of0
main thread sequence of6,loop of0
main thread sequence of7,loop of0
main thread sequence of8,loop of0
main thread sequence of9,loop of0

    

3、实例---可阻塞队列

假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 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();
     }
   } 
 }


        使用方法:

                Lock lock = new ReentrantLock();

                Condition condition = lock.newCondition();

                this.wait()----》condition.await()

                this.notify()----》condition.signal()

注意:判断条件时用while防止虚假唤醒,等待在那里,唤醒后再进行判断,确认符合要求后再执行任务。


实例:

   有三个线程,主线程10次,第一个子线程10次,第二个子线程10次循环执行50次。用Condition方法实现

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

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<10;i++){	
						business.sub1(i);
				}
				
			}
			
		}).start();
		new Thread(new Runnable() {
			
			public void run() {
				for(int i=0;i<20;i++){	
						business.sub2(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();
		
		//private boolean bSholdSub=true;
		private int shouldsub=1;
		public void sub1(int i){
			lock.lock();
			try{
				while(shouldsub!=2){
					try {
						//this.wait();
						condition2.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				for(int j=0;j<10;j++){
					System.out.println("sub1 thread sequence of"+j+",loop of"+i);
				}
				//bSholdSub=false;
				//condition.signal();
				
				shouldsub=3;
				condition3.signal();
				
				//this.notify();//notify必须和synchronized一起用
			}finally{
				lock.unlock();
			}
			
		}
		
		public void sub2(int i){
			lock.lock();
			try{
				while(shouldsub!=3){
					try {
						//this.wait();
						condition3.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				for(int j=0;j<10;j++){
					System.out.println("sub2 thread sequence of"+j+",loop of"+i);
				}
				/*bSholdSub=false;
				condition.signal();*/
				
				shouldsub=1;
				condition1.signal();
				
				//this.notify();//notify必须和synchronized一起用
			}finally{
				lock.unlock();
			}
			
		}
		
		public void main(int i){
			lock.lock();
			try{
				while(shouldsub!=1){
					try {
						//this.wait();
						condition1.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				for(int j=0;j<10;j++){
					System.out.println("main thread sequence of"+j+",loop of"+i);
				}
				/*bSholdSub=true;
				//this.notify();
				condition.signal();*/
				
				shouldsub=2;
				condition2.signal();
				
			}finally{
				lock.unlock();
			}
		}
	}

}

运行结果为:

main thread sequence of0,loop of0
main thread sequence of1,loop of0
main thread sequence of2,loop of0
main thread sequence of3,loop of0
main thread sequence of4,loop of0
main thread sequence of5,loop of0
main thread sequence of6,loop of0
main thread sequence of7,loop of0
main thread sequence of8,loop of0
main thread sequence of9,loop of0
sub1 thread sequence of0,loop of0
sub1 thread sequence of1,loop of0
sub1 thread sequence of2,loop of0
sub1 thread sequence of3,loop of0
sub1 thread sequence of4,loop of0
sub1 thread sequence of5,loop of0
sub1 thread sequence of6,loop of0
sub1 thread sequence of7,loop of0
sub1 thread sequence of8,loop of0
sub1 thread sequence of9,loop of0
sub2 thread sequence of0,loop of0
sub2 thread sequence of1,loop of0
sub2 thread sequence of2,loop of0
sub2 thread sequence of3,loop of0
sub2 thread sequence of4,loop of0
sub2 thread sequence of5,loop of0
sub2 thread sequence of6,loop of0
sub2 thread sequence of7,loop of0
sub2 thread sequence of8,loop of0

sub2 thread sequence of9,loop of0

......

猜你喜欢

转载自blog.csdn.net/pengzhisen123/article/details/80299277