5、JUC系列之---线程通信

一、线程通信--示例

需求:

     input 设置resource ,  resource为name和sex,output输出resource

代码:

package com.lee.juc.comm;

public class ResourceDemo_01 {

	public static void main(String[] args) {
		Resource_01 r = new Resource_01();
		
		Input in = new Input(r);
		Output out = new Output(r);
		
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		
		t1.start();
		t2.start();
		
	}
}

//资源
class Resource_01{
	public String name;
	public String sex;
}

//生产者
class Input implements Runnable{
	Resource_01 r;
	public Input(Resource_01 r) {
		this.r = r;
	}

	public void run() {
		int x = 0 ;
		while(true) {
			
			if(x==0) {
				r.name = "lee";
				r.sex = "male";
			}else {
				r.name = "迪";
				r.sex = "女";
			}
			x = (x+1)%2;
		}
	}
}

//消费者
class Output implements Runnable{

	Resource_01 r;
	
	public Output(Resource_01 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			System.out.println(r.name+"...."+r.sex);
		}
	}
	
}




结果:

原因:input 设置了lee male后 又设置了name = 迪,sex还没有设置,output就输出了。

解决方法:input和output用同一个锁,只有输入完成后output才能输出,

                 output输出完成后,input才能输入

        

解决代码:

扫描二维码关注公众号,回复: 889449 查看本文章
package com.lee.juc.comm;

public class ResourceDemo_01 {

	public static void main(String[] args) {
		Resource_01 r = new Resource_01();
		
		Input in = new Input(r);
		Output out = new Output(r);
		
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		
		t1.start();
		t2.start();
		
	}
}

//资源
class Resource_01{
	public String name;
	public String sex;
}

//生产者
class Input implements Runnable{
	Resource_01 r;
	public Input(Resource_01 r) {
		this.r = r;
	}

	public void run() {
		int x = 0 ;
		while(true) {
			synchronized (r) {
				if(x==0) {
					r.name = "lee";
					r.sex = "male";
				}else {
					r.name = "迪";
					r.sex = "女";
				}
				x = (x+1)%2;	
			}
			
		}
	}
}

//消费者
class Output implements Runnable{

	Resource_01 r;
	
	public Output(Resource_01 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			synchronized (r) {
				System.out.println(r.name+"...."+r.sex);
			}
		}
	}
	
}




结果:

问题:   input了一个资源,却output多个。

二、线程通信--等待唤醒

1、这些方法都是Object的方法:

         wait   让线程处于冻结状态,被wait的线程会被存储在线程池中

         notify  唤醒线程池中任意一个线程

         notifyAll  唤醒线程池中的所有线程

2、代码

package com.lee.juc.comm;

public class ResourceDemo_02 {

	public static void main(String[] args) {
		Resource_02 r = new Resource_02();
		
		Input_02 in = new Input_02(r);
		Output_02 out = new Output_02(r);
		
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		
		t1.start();
		t2.start();
		
	}
}

//资源
class Resource_02{
	public String name;
	public String sex;
	public boolean flag = false;//没有定义name和sex
}

//生产者
class Input_02 implements Runnable{
	Resource_02 r;
	public Input_02(Resource_02 r) {
		this.r = r;
	}

	public void run() {
		int x = 0 ;
		while(true) {
			synchronized (r) {
				if(r.flag==true) {
					try {r.wait();} catch (InterruptedException e) {e.printStackTrace();}
				}else {
					if(x==0) {
						r.name = "lee";
						r.sex = "male";
					}else {
						r.name = "迪";
						r.sex = "女";
					}
					x = (x+1)%2;
					r.flag=true;
					r.notify();
				}
			}
			
		}
	}
}

//消费者
class Output_02 implements Runnable{

	Resource_02 r;
	
	public Output_02(Resource_02 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			synchronized (r) {
				if(r.flag==false) {
					try {r.wait();} catch (InterruptedException e) {e.printStackTrace();}
				}else {
					System.out.println(r.name+"...."+r.sex);
					r.flag=false;
					r.notify();
				}
			}
		}
	}
	
}

 3、结果:

3、代码优化

package com.lee.juc.comm;

public class ResourceDemo_03 {

	public static void main(String[] args) {
		Resource_03 r = new Resource_03();
		
		Input_03 in = new Input_03(r);
		Output_03 out = new Output_03(r);
		
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		
		t1.start();
		t2.start();
		
	}
}

//资源
class Resource_03{
	private String name;
	private String sex;
	private boolean flag = false;//没有定义name和sex
	
	public synchronized void set(String name,String sex) {
		if(flag)
			try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
		this.name = name;
		this.sex = sex;
		flag=true;
		this.notify();
	}
	
	public synchronized void out() {
		if(!flag)
			try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}	
		System.out.println(name+"...+++..."+sex);
		flag=false;
		notify();
			
	}
	
	
}

//生产者
class Input_03 implements Runnable{
	Resource_03 r;
	public Input_03(Resource_03 r) {
		this.r = r;
	}

	public void run() {
		int x = 0 ;
		while(true) {
			if(x==0) {
				r.set("lee", "male");
			}else {
				r.set("迪", "女");
			}
			x = (x+1)%2;
		}
	}
}

//消费者
class Output_03 implements Runnable{

	Resource_03 r;
	
	public Output_03(Resource_03 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			r.out();
		}
	}
	
}




三、线程通信--多生产者、多消费者

1、流程图

2、代码

package com.lee.juc.comm;

public class ProducerConsumerDemo_01 {

	public static void main(String[] args) {
		Resource_01 r = new Resource_01();
		
		Producer_01 pro = new Producer_01(r);
		Consumer_01 con = new Consumer_01(r);
		
		Thread t0 = new Thread(pro);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(con);
		
		t0.start();
		t1.start();
		t2.start();
		t3.start();
		
	}
}

class Resource_01{
	private String name;
	private Integer count=1;
	private boolean flag = false;
	
	public synchronized void set(String name) {
		while(flag)//================
			try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
		this.name = name+""+count;
		count++;
		System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
		this.flag=true;
		this.notifyAll();//===============
	}
	
	public synchronized void out() {
		while(!flag)//=============
			try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}
		System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
		this.flag=false;
		this.notifyAll();//===================
	}
}

class Producer_01 implements Runnable{
	Resource_01 r;
	public Producer_01(Resource_01 r) {
		this.r = r;
	}

	public void run() {
		while(true) {
			r.set("烤鸭");
		}
	}
}

class Consumer_01 implements Runnable{

	Resource_01 r;
	public Consumer_01(Resource_01 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			r.out();
		}
	}
	
}

2、结果

四、Lock和Condition

1、Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。

简单的说Lock即是对synchronized的拓展。

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

代码:

package com.lee.juc.comm;

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

public class LockDemo {

	public static void main(String[] args) {
		Resource_05 r = new Resource_05();
		
		Producer_02 pro = new Producer_02(r);
		Consumer_02 con = new Consumer_02(r);
		
		Thread t0 = new Thread(pro);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(con);
		
		t0.start();
		t1.start();
		t2.start();
		t3.start();
		
	}
}

class Resource_05{
	private String name;
	private Integer count=1;
	private boolean flag = false;
	
	Lock lock = new ReentrantLock();
	Condition producter_con = lock.newCondition();
	Condition consumer_con = lock.newCondition();
	
	public void set(String name) {
		
		lock.lock();
		try {
			while(flag)
				try {producter_con.await();} catch (InterruptedException e) {e.printStackTrace();}
			this.name = name+""+count;
			count++;
			System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
			this.flag=true;
			consumer_con.signal();
		} finally {
			lock.unlock();
		}
		
		
	}
	
	public void out() {
		lock.lock();
		try {
			while(!flag)
				try {consumer_con.await();} catch (InterruptedException e) {e.printStackTrace();}
			System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
			this.flag=false;
			producter_con.signal();
		} finally {
			lock.unlock();
		}
		
	}
}

class Producer_02 implements Runnable{
	Resource_05 r;
	public Producer_02(Resource_05 r) {
		this.r = r;
	}

	public void run() {
		while(true) {
			r.set("烤鸭");
		}
	}
}

class Consumer_02 implements Runnable{

	Resource_05 r;
	public Consumer_02(Resource_05 r) {
		this.r = r;
	}
	
	public void run() {
		while(true) {
			r.out();
		}
	}
	
}

猜你喜欢

转载自my.oschina.net/u/3551274/blog/1812733
今日推荐