Java同時プログラミング---スレッド間の通信問題


一.スレッド間の通信
           1.コンセプト
スレッドはオペレーティングシステムにおける独立した個体であるが、これらは特殊な処理を経ることなく全体とすることができず、スレッド間の通信は全体の必須の方式の一つとなる.スレッドに通信指揮が存在すると、システム間のインタラクティビティがより強くなり、CPUの利用率を高めると同時に、開発者にスレッドタスクの処理過程において有効な制御と監督を行う.
           
            2.コードの例
2.1オリジナル方式によるスレッド通信の実現
package com.thread.message;

import java.util.ArrayList;
import java.util.List;

public class ListAdd1 {

	/**volatile       ,    notify wait   */
	private volatile static List list = new ArrayList();

	public void add() {
		list.add("bjsxt");
	}

	public int size() {
		return list.size();
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final ListAdd1 list1 = new ListAdd1();
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					for (int i = 0; i < 10; i++) {
						list1.add();
						System.out.println("    : " + Thread.currentThread().getName() + "       ..");
						Thread.sleep(1000);
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}, "t1");

		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true){
					if(list1.size() == 5){
						System.out.println("        : " + Thread.currentThread().getName() + "list size = 5     ...");
						throw new RuntimeException();
					}
				}
			}
		},"t2");
		
		t1.start();
		try {
			Thread.sleep(5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t2.start();
	}

}

     
2.2 wait/notifyメソッドによるスレッド間の通信
package com.thread.message;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.omg.Messaging.SyncScopeHelper;

/**
 * wait notify   , wait   ,notify    
 *         
 * @author Administrator
 *
 */
public class ListAdd2 {

	private volatile static List list = new ArrayList();

	public void add() {
		list.add("bjsxt");
	}

	public int size() {
		return list.size();
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final ListAdd2 list2 = new ListAdd2();

		// 1.       lock
		//    wait notify   ,      synchronized      
		final Object lock = new Object(); //         
		final CountDownLatch countDownLatch = new CountDownLatch(1);

		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					synchronized (lock) {
						for (int i = 0; i < 10; i++) {
							list2.add();
							System.out.println("    : " + Thread.currentThread().getName() + "       ..");
							Thread.sleep(500);
							if (list2.size() == 5) {
								System.out.println("      !");
								// countDownLatch.countDown();        //    ,   ,      
								lock.notify();
							}
						}
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}, "t1");

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				synchronized (lock) {        //     
					if (list2.size() == 5) {
						try {
							System.out.println("t2  ... ");
		//					countDownLatch.await();
							lock.wait();                     //  notif        
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}	
					}
					System.out.println("        : " + Thread.currentThread().getName() + "         ...");
					throw new RuntimeException();
				}
				
			}
		}, "t2");
		
		t2.start();   
		try {
			Thread.sleep(5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t1.start();
	}

}

   
3.コード分析
wait/notify法を用いるスレッド間の通信を実現する.(注意この2つの方法はいずれもObjectクラスの方法である.換言すればJavaはすべてのオブジェクトにこの2つの方法を提供している)
3.1 waitとnotifyはsynchronizedキーワードと組み合わせて使用する必要があります
3.2 waitメソッドロック解除、notifyメソッドロック解除しない