スレッド同期コンポーネント

5456 ワード

同時アクセスリソースの制御


    
semaphoreはカウンタであり、1つ以上の共有リソースへのアクセスを保護します.スレッドが共有リソースにアクセスする場合は、まずsemaphoreを取得する必要があります.semaphore内部カウンタが0より大きい場合は、semaphoreのカウンタが1つ減少し、共有リソースへのアクセスが許可されます.カウンタが0より大きいことは、freeリソースが使用可能であることを意味する.そうでない場合、semaphoreのカウンタが0の場合、semaphoreはカウンタが0より大きいまでスレッドをsleep状態に配置します.semaphoreのカウンタは0であり、すべての共有リソースが他のスレッドで使用されることを意味します.スレッドが共有リソースを完了したら、semaphoreを解放する必要があります.他のスレッドは共有スレッドにアクセスできます.
Semaphore semaphore = new Semaphore(1);
public void printJob (Object document){
   try {
      semaphore.acquire();
      long duration=(long)(Math.random()*10);
      System.out.printf("%s: PrintQueue: Printing a Job during %d 
seconds
",Thread.currentThread().getName(),duration); Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }
semaphore.acquire()// , semaphore , , InterruptedException 
semaphore.acquireUninterruptibly()// , 
tryAcquire()// , false, 

複数のリソースへの同時アクセスの制御

private boolean freePrinters[] = new boolean[3];
Lock lockPrinters = new ReentrantLock();
Semaphore semaphore = new Semaphore(3);  
public void printJob (Object document){
	try {
      semaphore.acquire();// 
      int assignedPrinter=getPrinter();// 
      long duration=(long)(Math.random()*10);
      System.out.printf("%s: PrintQueue: Printing a Job in Printer 
          %d during %d seconds
",Thread.currentThread().getName(),\ assignedPrinter,duration); TimeUnit.SECONDS.sleep(duration); freePrinters[assignedPrinter]=true; } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } } private int getPrinter() { try { lockPrinters.lock();// for (int i=0; i<freePrinters.length; i++) { if (freePrinters[i]){ ret=i; freePrinters[i]=false; break; } }catch (Exception e) { e.printStackTrace(); } finally { lockPrinters.unlock(); } return ret; }

複数の同時イベントの待機


Javaでは、一連の操作が完了するまで1つ以上のスレッドを待機させることができます.CountDownLatchは、1つの整数で初期化されます.すなわち、待機操作の数です.1つのスレッドがこれらの操作が完了するまで、await()メソッドを使用して、操作が完了するまでスレッドをsleep状態にします.1つの操作が完了するとcountDown()が呼び出されます.
CountDownLatch controller = new CountDownLatch(number);

controller.countDown();// 
try {
      controller.await();// 
      System.out.printf("VideoConference: All the participants 
have come
"); System.out.printf("VideoConference: Let's start...
"); } catch (InterruptedException e) { e.printStackTrace(); }

CountDownLatchオブジェクトを作成し、コンストラクタパラメータを使用して内部カウンタを初期化し、各スレッドがcountDown()メソッドを呼び出し、CountDownLatchオブジェクトの内部カウンタが1から減算され、内部カウンタが0の場合、CountDownLatchオブジェクトはawait()メソッドで待機しているスレッドを呼び覚ます.カウンタが0になると、すべての呼び出しawait()メソッドがすぐに返され、すべてのcountDown()呼び出しは有効になりません.CountDownLatchメカニズムは、1つまたは複数のスレッドを同期するために複数のタスクを使用します.再同期が必要な場合は、新しいCountDownLatchオブジェクトを作成する必要があります.

同時タスク間でのデータ交換


Javaは、2つのパラレルスレッド間でデータを交換する同期コンポーネントを提供します.Exchangerクラスでは、2つのスレッド間の同期ポイントを定義できます.2つのスレッドがこのポイントに到達すると、データ構造が交換され、最初のスレッドのデータ構造が2番目のスレッドに流れ、2番目のスレッドのデータが1番目のスレッドに流れます.
public class ThreadLocalTest {    
    public static void main(String[] args) {  
        Exchanger<List<Integer>> exchanger = new Exchanger<>();  
        new Consumer(exchanger).start();  
        new Producer(exchanger).start();  
    }    
}  
  
class Producer extends Thread {  
    List<Integer> list = new ArrayList<>();  
    Exchanger<List<Integer>> exchanger = null;  
    public Producer(Exchanger<List<Integer>> exchanger) {  
        super();  
        this.exchanger = exchanger;  
    }  
    @Override  
    public void run() {  
        Random rand = new Random();  
        for(int i=0; i<10; i++) {  
            list.clear();  
            list.add(rand.nextInt(10000));  
            list.add(rand.nextInt(10000));  
            list.add(rand.nextInt(10000));  
            list.add(rand.nextInt(10000));  
            list.add(rand.nextInt(10000));  
            try {  
                list = exchanger.exchange(list);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
    }  
}    
class Consumer extends Thread {  
    List<Integer> list = new ArrayList<>();  
    Exchanger<List<Integer>> exchanger = null;  
    public Consumer(Exchanger<List<Integer>> exchanger) {  
        super();  
        this.exchanger = exchanger;  
    }  
    @Override  
    public void run() {  
        for(int i=0; i<10; i++) {  
            try {  
                list = exchanger.exchange(list);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
            System.out.print(list.get(0)+", ");  
            System.out.print(list.get(1)+", ");  
            System.out.print(list.get(2)+", ");  
            System.out.print(list.get(3)+", ");  
            System.out.println(list.get(4)+", ");  
        }  
    }  
}