サイケたCountDownLatchによって複雑解決

たCountDownLatchの決意

たCountDownLatchは何ですか

たCountDownLatch AQSは、すべてのスレッドが実行を完了するまで、1つ以上のスレッドをブロックし、ツールをブロックに基づいています。

問題を解決したCountDownLatch

タスクは、様々なサブタスクに分割する必要がある場合に、より大きな操作は、サブタスクはすべて一緒に来て、総タスクの後に完了しなければならないよりも、ときに。
シミュレーションの同時使用は、たCountDownLatch。あなたはまた、タイムアウトの待機時間を設定することができたときに使用することができます

たCountDownLatchの使用状況

実行完了後に実行の1ブロックは、すべてのスレッド

@Slf4j
public class CountDownLatchExample {
    //线程数量
    private static final int THREAD_NUM = 10;

    // CountdownLatch阻塞模拟
    public static void main(String[] args) throws InterruptedException {

        // 创建线程池 用于执行线程
        ExecutorService executorService = Executors.newCachedThreadPool();
        //创建countDownLatch
        final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
        long startTime = System.currentTimeMillis();
        //循环创建线程
        for (int i = 0; i < THREAD_NUM; i++) {
            final int a = i;

            executorService.execute(() -> {
                try {
                    test(a);
                } catch (Exception e) {
                    log.error("Exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });

        }

        countDownLatch.await();
        long endTime = System.currentTimeMillis();
        log.info("执行完毕,{}-{}",startTime,endTime);
        executorService.shutdown();
    }

    private static void test(int num) throws InterruptedException {
        Thread.sleep(100);
        log.info("{}-{}", num,System.currentTimeMillis());
        Thread.sleep(100);
    }

}

结果
10:56:02.544 [プール1スレッド5] INFO AQSExample.CountDownLatchExampleTimeOutTest - 4から1559271362542
10:56:02.543 [プール1スレッド2] INFO AQSExample.CountDownLatchExampleTimeOutTest - 1から1559271362541
10:56:02.548 [プール1スレッド10] INFO AQSExample.CountDownLatchExampleTimeOutTest - 9から1559271362548
10:56:02.544 [プール1スレッド7] INFO AQSExample.CountDownLatchExampleTimeOutTest - 6から1559271362543
10:56:02.543 [プール1スレッド-4] INFO AQSExample.CountDownLatchExampleTimeOutTest - 3から1559271362542
10:56:02.544 [プール1スレッド3] INFO AQSExample.CountDownLatchExampleTimeOutTest - 2から1559271362541
10:56:02.544 [プール1スレッド8] INFO AQSExample。 CountDownLatchExampleTimeOutTest - 7-1559271362543
10:56:02.544 [プール1スレッド6] INFO AQSExample.CountDownLatchExampleTimeOutTest - 5から1559271362543
10:56:02.543 [プール1スレッド1] INFO AQSExample.CountDownLatchExampleTimeOutTest - 0から1559271362541
10:56:02.548 [プール1スレッド9] INFO AQSExample.CountDownLatchExampleTimeOutTest - 8から1559271362548
10:56:02.548 [メイン] INFO AQSExample.CountDownLatchExampleTimeOutTest -执行完毕、1559271362441から1559271362548

結果は、スレッドが皇帝の印刷が終了する前にすべてのスレッド、見ることができる「完成されています。」

実行2.タイムアウトブロックすべてのスレッド、時間後に直接リリース。

私たちは、後にタイムアウトを設定した場合

@Slf4j
public class CountDownLatchExampleTimeOutTest {


    //线程数量
    private static final int THREAD_NUM = 10;

    // CountdownLatch阻塞模拟
    public static void main(String[] args) throws InterruptedException {
        // 创建线程池 用于执行线程
        ExecutorService executorService = Executors.newCachedThreadPool();
        //创建countDownLatch
        final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
        //循环创建线程
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUM; i++) {
            final int a = i;
            executorService.execute(() -> {
                try {
                    test(a);
                } catch (Exception e) {
                    log.error("Exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });

        }

        countDownLatch.await(10,TimeUnit.MILLISECONDS);
        long endTime = System.currentTimeMillis();
        log.info("执行完毕,{}-{}",startTime,endTime);
        executorService.shutdown();
    }

    private static void test(int num) throws InterruptedException {
        Thread.sleep(50);
        log.info("{}-{}", num,System.currentTimeMillis());
    }
}

50ミリ秒で、その後、実行の遅延後の各スレッドは、カウントが優先順位を計時しているのでとても完成実行の結果をプリントアウト。そして、スレッドの内容に進みます。

结果
11:14:55.509 [メイン] INFO AQSExample.CountDownLatchExampleTimeOutTest -执行完毕、1559272495373から1559272495506
11:14:55.542 [プール1スレッド1] INFO AQSExample.CountDownLatchExampleTimeOutTest - 0から1559272495542
11:14:55.542 [プール| 1スレッド2] INFO AQSExample.CountDownLatchExampleTimeOutTest - 1から1559272495542
11:14:55.543 [プール1スレッド3] INFO AQSExample.CountDownLatchExampleTimeOutTest - 2から1559272495543
11:14:55.543 [プール1スレッド4] INFO AQSExample.CountDownLatchExampleTimeOutTest - 3-1559272495543
11:14:55.543 [プール1スレッド5] INFO AQSExample.CountDownLatchExampleTimeOutTest - 4から1559272495543
11:14:55.544 [プール1スレッド6] INFO AQSExample.CountDownLatchExampleTimeOutTest - 5 -1559272495544
11:14:55.544 [プール1スレッド7] INFO AQSExample.CountDownLatchExampleTimeOutTest - 6から1559272495544
11:14:55.545 [プール1スレッド9] INFO AQSExample.CountDownLatchExampleTimeOutTest - 8から1559272495545
11:14:55.545 [プール1スレッド8] INFO AQSExample.CountDownLatchExampleTimeOutTest - 7から1559272495545
11:14:55.545 [プール1スレッド10] INFO AQSExample.CountDownLatchExampleTimeOutTest - 9から1559272495545

たCountDownLatchソースの解析

メソッドとプロパティのたCountDownLatchソースは多くはありません、の各解像度で見てみましょう。

そして、フレーム工法1.AQS

//当前对象中私有阻塞工具
private final Sync sync;
// 模板方法模式重写AQS工具
private static final class Sync extends AbstractQueuedSynchronizer {
   private static final long serialVersionUID = 4982264981922014374L;
   // 共享阻塞AQS
   Sync(int count) {
       setState(count);
   }
   // 获取当前还剩多少资源可以使用
   int getCount() {
       return getState();
   }

   protected int tryAcquireShared(int acquires) {
       return (getState() == 0) ? 1 : -1;
   }

   protected boolean tryReleaseShared(int releases) {
       for (;;) {
           int c = getState();
           if (c == 0)
               return false;
           int nextc = c-1;
           if (compareAndSetState(c, nextc))
               return nextc == 0;
       }
   }
}
//构造方法创建一个锁对象
public CountDownLatch(int count) {
   if (count < 0) throw new IllegalArgumentException("count < 0");
   this.sync = new Sync(count);
}

2.countDown()メソッドの構文解析

このメソッドは、スレッド数を引い統計の数の実装後に使用され、

// 该方法时释放一个共享锁。当所有锁都被释放完成后主线程就能继续执行了。
public void countDown() {
    sync.releaseShared(1);
}

3.await()メソッドの構文解析

//拦截主线程的方法。主线程在这里等待条件达成后继续执行。
public void await() throws InterruptedException {
    //在这里阻塞线程的执行
    sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
       throws InterruptedException {
   if (Thread.interrupted())
       throw new InterruptedException();
    //这里判断是否还有可以共享的资源
   // 如果有则返回-1 否则返回 1,重写AQS的方法参见(1.AQS框架以及构造方法)
   if (tryAcquireShared(arg) < 0)
       // 有资源则运行阻塞自旋等待所有线程执行完毕
       doAcquireSharedInterruptibly(arg);
   // 无资源可用就让线程继续执行
}

// 带延迟的减少数据拦截方法
// 返回的结果是没有跑完全部线程就继续执行下一步了。
public boolean await(long timeout, TimeUnit unit)
    throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
    throws InterruptedException {
    //线程如果被中断则抛出异常
    if (Thread.interrupted())
        throw new InterruptedException();
    // 表示如果线程被执行完了直接返回成功,如果没有执行完则看等待时间来决定是否要继续执行。
    return tryAcquireShared(arg) >= 0 ||
        doAcquireSharedNanos(arg, nanosTimeout);
}

たCountDownLatch問題

たCountDownLatchカウンタが完全にリセットすることはできません、あなたは障害物の次のラウンドへの完全な使用されたCountDownLatchを再作成する必要があります。フォローアップのツールは、この問題を解決するためのツールを持っています

たCountDownLatchの概要

たCountDownLatchこのクラスは、他のスレッドが実行前に自分の仕事を完了するのを待っているスレッドを可能にします。チェンは、合成、ローディング・リソースによる処理の均一な分散の算出結果の点で非有用な結果を有します。次は、ラッチツールCyclicBarrierをでカウンターをリセットすることについて説明します。

おすすめ

転載: www.cnblogs.com/yanlong300/p/10954848.html