二、JUC系列之---線程通訊

1、線程通訊--示例

需求:java

     input 設置resource ,  resource爲name和sex,output輸出resource優化

代碼:this

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);
		}
	}
	
}

結果:spa

緣由:input 設置了lee male後 又設置了name = 迪,sex尚未設置,output就輸出了。線程

解決方法:input和output用同一個鎖,只有輸入完成後output才能輸出,code

                 output輸出完成後,input才能輸入對象

        

解決代碼:資源

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);
			}
		}
	}
	
}

結果:get

問題:   input了一個資源,卻output多個。input

2、線程通訊--等待喚醒

一、這些方法都是Object的方法:

         wait   讓線程處於凍結狀態,被wait的線程會被存儲在線程池中

         notify  喚醒線程池中任意一個線程

         notifyAll  喚醒線程池中的全部線程

二、代碼

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();
				}
			}
		}
	}
	
}

 三、結果:

三、代碼優化

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();
		}
	}
	
}

3、線程通訊--多生產者、多消費者

一、流程圖

 

二、代碼

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();
		}
	}
	
}

二、結果

4、Lock和Condition

一、Lock 實現提供了比使用 synchronized 方法和語句可得到的更普遍的鎖定操做。此實現容許更靈活的結構,能夠具備差異很大的屬性,能夠支持多個相關的 Condition 對象。

簡單的說Lock便是對synchronized的拓展。

二、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();
		}
	}
	
}
相關文章
相關標籤/搜索