JAvaスレッドの通信とスレッドプール

3681 ワード

1.従来のスレッド通信
   synchronized修飾の同期メソッドまたは同期コードブロックを使用すると、wait()、notify()、notifyAll()の3つのメソッドがメソッド体重で直接呼び出されます.次のようになります.
   wait():現在のスレッドを待機させ、他のスレッドが同期モニタを呼び出すnotify()またはnotifyAll()メソッドを知る.
   notify():この同期モニタで待機している単一のスレッドを起動します.
   notifyAll():この同期モニタで待機しているすべてのスレッドを起動します.
2.Condition制御スレッドによる通信
   プログラムでsynchronizedキーワードを用いて同期を実現しない場合,ロックオブジェクトを直接用いて同期を保証する場合,上記3つの方法は使用できない.ロックオブジェクトのnewCondition()メソッドで返されるConditionインスタンスを使用して、同期通信を制御するのが一般的です.すなわち,Conditionクラスのawait(),signal(),signalAll()メソッドを用いて,上述した3つのメソッドをそれぞれ代替する.
3.ブロックキューを使用してスレッド通信を制御する
  BlockingQueueはQueueのサブインタフェースですが、あるスレッドがBloockingQueueに要素を入れようとすると、キューがいっぱいになるとスレッドがブロックされ、逆にあるスレッドがキューから要素を取り、キューが空になるとスレッドもブロックされます.次のようになります.
import java.util.concurrent.*;
class Producer extends Thread 
{
	private BlockingQueue bq;
	public Producer(BlockingQueue bq)
	{
		this.bq=bq;
	}
	@Override
	public void run()
	{
		String[] strArr=new String[]{"Java","  ","Spring"};
		for(int i=0;i<33333;i++)
		{
			System.out.println(getName()+"     ");
			try
			{
				Thread.sleep(200);
				bq.put(strArr[i%3]);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println(getName()+"    :"+bq);
		}
	}
}
class Consumer extends Thread
{
	private BlockingQueue bq;
	public Consumer(BlockingQueue bq)
	{
		this.bq=bq;
	}
	@Override
	public void run()
	{
		while(true)
		{
			System.out.println(getName()+"       !");
			try
			{
				Thread.sleep(200);
				bq.take();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println(getName()+"    :"+bq);
		}
	}
}
public class BlockingQueueTest2 
{
	public static void main(String[] args) 
	{//              
		//    1        
		BlockingQueue bq=new ArrayBlockingQueue<>(1);
		//  3       1      
		new Producer(bq).start();
		new Producer(bq).start();
		new Producer(bq).start();
		new Consumer(bq).start();
	}
}
4.スレッドプール
  システムが新しいスレッドを起動するコストが高いため、スレッドプールを使用すると、システムの起動時に大量の空きスレッドを作成でき、スレッドプールはシステムで同時に実行されるスレッドの数を効果的に制御し、システムの効率的な性能を維持することができます.使用方法は次のとおりです.
import java.util.concurrent.*;
class MyThread implements Runnable 
{//  Runnable            
	public void run()
	{
		for(int i=0;i<100;i++)
		{
			System.out.println(Thread.currentThread().getName()+"i   :"+i);
		}
	}
	public static void main(String[] args) 
	{
		//            
		ExecutorService pool=Executors.newFixedThreadPool(6);
		//       2   
		pool.submit(new MyThread());
		pool.submit(new MyThread());
		pool.shutdown();//     
	}
}

  スレッドプールを使用して、複数の分解タスクを計算します.
import java.util.concurrent.*;
import java.util.*;
class CalTask extends RecursiveTask 
{//              
	//      20  
	private static final int THREADHOLD=20;
	private int arr[];//    
	private int start;//    
	private int end;//    
	public CalTask(int[] arr,int start,int end)
	{
		this.arr=arr;
		this.start=start;
		this.end=end;
	}
	@Override
	protected Integer compute()
	{//      
		int sum=0;
		if(end-start future=pool.submit(new CalTask(arr,0,arr.length));
		//        
		System.out.println(future.get());
		pool.shutdown();
	}
}