多线程(三)

6、线程间通信(保证线程有序)

生产者-消费者问题

考虑问题如下:

1)若消费者先抢到CPU执行权,会先消费资源,但此时没有资源 ,应当生产者生产资源之后再消费;

2)若生产者先抢到CPU执行权,会先生产资源,但此时有资源,应当消费者消费资源之后再生产;

解决思路:

1)对生产者而言,先查看是否有资源,有就等待,等待消费者消费完之后,通知生产

2)对消费者而言,先查看是否有资源,无就等待,等待生产者生产完之后,通知消费


等待-唤醒机制实现线程间通信,Java提供如下API:

public final void wait()

在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

public final void notify()

唤醒在此对象监视器上等待的单个线程。

public final void notifyAll()

唤醒在此对象监视器上等待的所有线程。


Student类表示资源:

public class Student {
	String name;
	int age;
	boolean flag;//标记位,表示是否有资源
}

线程间通信:

public class ThreadCommunication {
	
	public static class SetThread implements Runnable{

		private Student s;
		private int x=0;
		
		public SetThread(Student s) {
			this.s=s;
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){				
				//同步块
				synchronized (s) {
					//等待唤醒机制
					if(s.flag){//线程1判断是否有资源,有则等待,等待线程2消费完再生产
						try {
							s.wait();//等待,并且立即释放锁
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
					//无资源,则生产
					if(x%2==0){
						s.name="周杰伦";
						s.age=29;
					}else{
						s.name="薛之谦";
						s.age=26;
					}
					x++;
					
					//生产完,修改标记
					s.flag=true;
					//唤醒正在wait的线程,即t2
					s.notify();
				}
				//醒着的线程继续争抢CPU执行权,即t1、t2;
				//若t1争抢到CPU执行权,则继续循环,根据标记flag判断,会进入等待,此时t2执行;
				//若t2争抢到CPU执行权,根据标记flag判断,继续执行。
				//所以,这个等待唤醒机制就保证了下一个一定是t2执行!!!
			}
		}
		
	}
	
	public static class GetThread implements Runnable{

		private Student s;
		
		public GetThread(Student s) {
			this.s=s;
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){
				synchronized (s) {
					if(!s.flag){//线程2判断是否有资源,没有就等待,等待线程1生产资源
						try {
							s.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
					//有资源,则消费
					System.out.println(s.name+":"+s.age);
					
					//消费完,修改标记
					s.flag=false;
					//唤醒正在wait的线程,即t1
					s.notify();
				}
				//醒着的线程继续争抢CPU执行权,即t1、t2;
				//同样,这个等待唤醒机制就保证了下一个一定是t1执行!!!
			}
		}
		
	}
	
	public static void main(String[] args) {
		Student s=new Student();
		
		Thread t1=new Thread(new SetThread(s));
		Thread t2=new Thread(new GetThread(s));
		
		t1.start();
		t2.start();
	}
}

输出:

周杰伦:29
薛之谦:26
周杰伦:29
薛之谦:26
周杰伦:29
薛之谦:26
周杰伦:29
薛之谦:26
周杰伦:29
薛之谦:26
周杰伦:29
薛之谦:26
周杰伦:29


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值