Javaコンカレントプログラミングの同時実行制御クラス

CountDownLatch

1つ以上のスレッドが、他のスレッドが操作を完了するのを待つことを許可します。    

public static void main(String[] args) throws InterruptedException {

     final CountDownLatch c = new CountDownLatch(2);

        new Thread(new Runnable() {

            @Override

            public void run() {

                c.countDown();

                System.out.println("线程1执行完成");

            }

        }).start();

        new Thread(new Runnable() {

         @Override

         public void run() {

         c.countDown();

         System.out.println("线程2执行完成");

         }

        }).start();


        c.await();

        System.out.println("退出");

}

結果:

スレッド1の実行が完了しました

スレッド2の実行が完了しました

脱落

 

CountDownLatchのコンストラクターは1つを受け取ります。ここで、構築パラメーターnは、n回の完了を待機すること、つまりcountDownをn回実行することを意味します。

CyclicBarrier

スレッドのグループは、最後のスレッドがバリアに到達するまで、バリア(同期ポイントとも呼ばれます)に到達するとブロックされます。    

public static void main(String[] args) {

        new Thread(new Runnable() {


            @Override

            public void run() {

                try {

                    c.await();

                } catch (Exception e) {


                }

                System.out.println(1);

            }

        }).start();


        try {

            c.await();

        } catch (Exception e) {


        }

        System.out.println(2);

}

2つのスレッドがc.await()を実行すると、現在のバリアが2つのスレッドをインターセプトすることを意味します。CyclicBarrierインターセプトパラメーターを比較します。同期標準に達した場合、2つのスレッドは実行を継続します。例:new CyclicBarrier(2); if count! = 0の場合、2つのスレッドは待機を続けます。

ソースコード分析:    

public CyclicBarrier(int parties, Runnable barrierAction) {

        if (parties <= 0) throw new IllegalArgumentException();

//在barrier被触发之前必须调用的线程数

        this.parties = parties;

        this.count = parties;

//在barrier被触发时调用action

        this.barrierCommand = barrierAction;

    }

    public CyclicBarrier(int parties) {

        this(parties, null);

}

    public int await() throws InterruptedException, BrokenBarrierException {

        try {

            return dowait(false, 0L);

        } catch (TimeoutException toe) {

            throw new Error(toe); // cannot happen

        }

    }

}

private int dowait(boolean timed, long nanos)

        throws InterruptedException, BrokenBarrierException,

               TimeoutException {

//.....

int index = --count;

            if (index == 0) {  // tripped

//....

nextGeneration();

return 0;

//....

}

trip.await();

//.....

}

    private void nextGeneration() {

        // signal completion of last generation

        trip.signalAll();

        // set up next generation

        count = parties;

        generation = new Generation();

}

これは簡単な分析です。

セマフォ

セマフォ(セマフォ)は、特定のリソースに同時にアクセスするスレッドの数を制御するために使用され、さまざまなスレッドを調整して、共通のリソースを適切に使用できるようにします。

Semaphoreの構築方法Semaphore(int permit)は、使用可能なライセンスの数を表す整数を受け入れます。セマフォ(10)は、10個のスレッドがライセンスを取得できることを意味します。つまり、最大同時数は10です。

Semaphoreのacquire()メソッドはライセンスを取得し、release()メソッドを呼び出して使用後にライセンスを返します。tryAcquire()メソッドを使用してライセンスの取得を試みることもできます。    

public static void main(String[] args) {

     ExecutorService threadPool   = Executors.newFixedThreadPool(10);

     final Semaphore       s            = new Semaphore(5);

        for (int i = 0; i < 30; i++) {

            threadPool.execute(new Runnable() {

                @Override

                public void run() {

                    try {

                        s.acquire();

                        System.out.println("save data");

                        s.release();

                    } catch (InterruptedException e) {

                    }

                }

            });

        }


        threadPool.shutdown();

}

分析:現在のスレッドプール内のスレッドの最大数は10で、実行する必要のあるタスクは30であり、同時に実行できるタスクの許容サイズは5です。つまり、タスク実行の同時実行性は、スレッド数とアクセス許可の影響を受けます。スレッド数は10ですが、同時に実行できるタスクは5つだけです。

 

セマフォの他の方法:

Int availablePermits():このセマフォで現在使用可能なライセンスの数を返します。

Int getQueueLength():ライセンスの取得を待機しているスレッドの数を返します。

ブールhasQueuedThreads():ライセンスの取得を待機しているスレッドがあるかどうか。

void reducePermits(int reduce):保護された方法である削減許可を削減します。

Collection getQueuedThreads():ライセンスの取得を待機しているすべてのスレッドのコレクションを返します。これは保護されたメソッドです。

エクスチェンジャー

Exchanger(Exchanger)は、スレッド間のコラボレーションのためのツールクラスです。Exchangerは、スレッド間のデータ交換に使用されます。これは、2つのスレッドが相互にデータを交換できる同期ポイントを提供します。2つのスレッドは交換メソッドを介してデータを交換します。最初のスレッドが最初にexchange()メソッドを実行すると、常に2番目のスレッドが交換メソッドを実行するのを待ちます。両方のスレッドが同期ポイントに到達すると、2つのスレッドはデータを交換し、このスレッドによって生成されたデータを相手に渡すことができます。

public static void main(String[] args) {

final Exchanger<String> exgr = new Exchanger<String>();

ExecutorService threadPool = Executors.newFixedThreadPool(2);

threadPool.execute(new Runnable() {

@Override

public void run() {

try {

String A = "银行流水A";// A录入银行流水数据

exgr.exchange(A);

} catch (InterruptedException e) {

}

}

});


threadPool.execute(new Runnable() {

@Override

public void run() {

try {

String B = "银行流水B";// B录入银行流水数据

String A = exgr.exchange("B");

System.out.println("A和B数据是否一致:" + A.equals(B) + ",A录入的是:" + A + ",B录入是:" + B);

} catch (InterruptedException e) {

}

}

});


threadPool.shutdown();


}

 

 

おすすめ

転載: blog.csdn.net/weixin_44416039/article/details/86162827