JAvaスレッド-スレッドの通信

3883 ワード

スレッド通信の3つの方式
同期
whileポーリング方式
wait()/notify()方式
 
スレッド通信の3つの方式
同期
ここでいう同期はsynchronizedキーワードでスレッド間の通信を実現し,コードで例示する.
class Obj{
	int count = 0;
	public synchronized void add(){
		//do something
		count++;
	}
	public synchronized void del(){
		//do something
		count--;
	}
}
public class Demo4 {
	static Obj obj = new Obj();
	public static void main(String[] args) {
		//  1
		new Thread(new Runnable(){
			public void run() {
				for(int i = 0;i < 10;i++){
					obj.add();
				}
			}
		}).start();
		//  2 
		new Thread(new Runnable(){
			public void run() {
				for(int i = 0;i < 5;i++){
					obj.del();
				}
			}
		}).start();
		//   
		while(Thread.activeCount() > 1){
			Thread.yield();
		}
		System.out.println("main:"+obj.count);
	}
} 

上記のコードを解析すると,スレッド1とスレッド2はobjというオブジェクトを操作し,スレッド1がadd()メソッドを実行するとobjというオブジェクトをロックとして取得し,このときスレッド2はdel()メソッドを行うことができない.スレッド1がadd()メソッドを実行した後にスレッド2が実行されると、スレッド間の通信が実現される.
この方法は本質的に共有変数式通信であり,誰がロックを手に入れたかは実行できる.
whileポーリング方式
この方式は2つのスレッドで1つのスレッドが絶えず条件を変更し、もう1つのスレッドにはwhileサイクルがあり、条件が成立するまで条件を判断し続け、他のコードブロックの実行を開始するが、実際には複数のスレッドが同時に実行され、この方式ではCPU性能の一部を犠牲にする.
class Obj{
	int count = 0;
	public synchronized void add(){
		//do something
		count++;
	}
	public synchronized void del(){
		//do something
		count--;
	}
}
public class Demo4 {
	static Obj obj = new Obj();
	public static void main(String[] args) {
		//  1
		new Thread(new Runnable(){
			@Override
			public void run() {
				for(int i = 0;i < 10;i++){
					obj.add();
					System.out.println("++");
				}
			}
		}).start();
		//  2
		new Thread(new Runnable(){
			@Override
			public void run() {
				boolean b = true;
				while(b){
					if(obj.count == 5){
						System.out.println("  2    ");
						b = false;
					}
				}
			}
		}).start();;
	}
	

上記のコードでは、スレッド2の条件が満たされない場合、無意味なループが行われている.
wait()/notify()方式
この方式には古典的な例がある.生産者-消費者モデルであり、倉庫の貨物が不足している場合、消費者は待たなければならない.生産者が十分な貨物を生産するのは消費者にメッセージを送ることであり、消費者は運行を続けることができる.同様に、倉庫がいっぱいになると生産者はしばらく停止する必要があり、一部の貨物が消費されると消費者は生産者にメッセージを送り、生産者が仕事を続けることができることを示した.
class Model {
	private int count;
	public Model(){
		this.count = 1000;
	}
	
	public synchronized void produce(int val){
		if(count > 5000){
			try {
				System.out.println("    ");
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			count += val;
			System.out.println("   1000-    :"+get());
			this.notify();
		}
	}

	public synchronized void consume(int val){
		if(count < val){
			System.out.println("    -    :"+get());
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			count -= val;
			System.out.println("   2000-    :"+get());
			this.notifyAll();
		}
		
	}
	public int get(){
		return this.count;
	}
}
public class Demo8 {
	public static void main(String[] args) {
		
		final Model model = new Model();
		 /**
		  *    
		  */
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					model.produce(1000);
				}
			}
		}).start();
		
		/**
		 *    
		 */
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){	
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					model.consume(2000);
				}
			}
		}).start();
	}
}

実行結果:
容量不足-現在容量:1000生産1000-現在容量:2000消費2000-倉庫容量:0生産1000-現在容量:1000容量不足-現在容量:1000生産1000-現在容量:2000生産1000-現在容量:2000生産1000-現在容量:3000消費2000-倉庫容量:1000生産1000-当前容量:2000消費2000-倉庫容量:0生産1000-現在容量:1000容量不足-現在容量:1000生産1000-現在容量:2000消費2000-倉庫容量:0