JAVA多线程编程Condition

正常的生产者消费者模式,按多线程的处理思路来,当条件满足的时候生产者通知消费者消费,条件不满足的时候,消费者通知生产者来生产,然后继续消费。这就涉及到线程间通信,前面我说volatile的时候讲过线程间通信有两种方式:一、通过公共变量。二、通过消息传递。volatile就是前者,后者前面也说了,wait(),notify()。就是典型的后者实现。但是wait() 和 notify()使用起来很笨重。下面先来看例子:

一个简单的买票小程序:

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

public class o1condition {
	public int count = 10;
	
	 synchronized void put(){
		try {
			while(count == 0){
				this.wait();
		}
			count--;
			System.out.println(Thread.currentThread().getName()+"消费了一个,当前还剩余"+count+"个");
			this.notifyAll();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	 synchronized void add(){
		 try {
			 while(count > 0){
				 this.wait();
			 }
				count++;
				System.out.println(Thread.currentThread().getName()+"生产了一个,当前还剩余+"+count);
				this.notifyAll();
		 } catch (Exception e) {
			// TODO: handle exception
		}
	 }

	public static void main(String [] args){
		
		waitnotify a = new waitnotify();
		
		for(int i=0; i<5; i++){
			new Thread(() -> {
				while(true){
					a.put();
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			},"消费者"+i).start();
		}
		
		for(int i=0; i<2; i++){
			new Thread(() -> {

				while(true){
					a.add();
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
			},"生产者"+i).start();
		}
		
	}
	
	
}

程序很简单,五个消费者,两个生产者。当count为0的时候,消费者通知生产者生产,如果count大于0的话,就通知消费者消费自己休息。这样有一个缺点,就是当唤醒的时候这个this会唤醒所有人,正常,如果count>0应该只唤醒消费者,而count = 0的话只需要唤醒生产者生产就可以了,notifyall()会唤醒所有人,这势必要带来系统额外的开销,并且显得不灵活。有没有更好的方法?有,当然有。

Condition

看代码:

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

import sun.text.resources.CollationData;

public class waitnotify {
	
	public int count = 10;
	
	ReentrantLock lock = new ReentrantLock();
	
	Condition produce = lock.newCondition();
	Condition consumer  = lock.newCondition();
	
	 void put(){
		 lock.lock();
		try {
			while(count == 0){
				consumer.await();
		}
			count--;
			System.out.println(Thread.currentThread().getName()+"消费了一个,当前还剩余"+count+"个");
			produce.signalAll();;
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			lock.unlock();
		}

	}
	
	 void add(){
		 lock.lock();
		 try {
			 while(count > 0){
				 produce.await();
			 }
				count++;
				System.out.println(Thread.currentThread().getName()+"生产了一个,当前还剩余+"+count);
				consumer.signalAll();
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			lock.unlock();
		}
	 }

	public static void main(String [] args){
		
		waitnotify a = new waitnotify();
		
		for(int i=0; i<5; i++){
			new Thread(() -> {
				while(true){
					a.put();
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			},"消费者"+i).start();
		}
		
		for(int i=0; i<2; i++){
			new Thread(() -> {

				while(true){
					a.add();
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
			},"生产者"+i).start();
		}
		
	}
	
	
}

我们可以精确指定消费者和生产者等待或者唤醒,这样比较灵活。

Conditiond需要配合Lock使用,而wait()notify()则需要配合synchronized使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值