Sike resolve complicated by the CountDownLatch

CountDownLatch resolve

What is CountDownLatch

CountDownLatch AQS is based on blocking tool, blocking one or more threads, until all threads have completed execution.

CountDownLatch solve the problem

When a larger operation than when a task needs to be split into various sub-tasks, sub-tasks must be completed after all come together and the total task.
Concurrent use of simulation can be used when CountDownLatch. You can also set the timeout wait time,

CountDownLatch usage

1. Block all threads of execution after the completion of execution

@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 [pool-1-thread-5] INFO AQSExample.CountDownLatchExampleTimeOutTest - 4-1559271362542
10:56:02.543 [pool-1-thread-2] INFO AQSExample.CountDownLatchExampleTimeOutTest - 1-1559271362541
10:56:02.548 [pool-1-thread-10] INFO AQSExample.CountDownLatchExampleTimeOutTest - 9-1559271362548
10:56:02.544 [pool-1-thread-7] INFO AQSExample.CountDownLatchExampleTimeOutTest - 6-1559271362543
10:56:02.543 [pool-1-thread-4] INFO AQSExample.CountDownLatchExampleTimeOutTest - 3-1559271362542
10:56:02.544 [pool-1-thread-3] INFO AQSExample.CountDownLatchExampleTimeOutTest - 2-1559271362541
10:56:02.544 [pool-1-thread-8] INFO AQSExample.CountDownLatchExampleTimeOutTest - 7-1559271362543
10:56:02.544 [pool-1-thread-6] INFO AQSExample.CountDownLatchExampleTimeOutTest - 5-1559271362543
10:56:02.543 [pool-1-thread-1] INFO AQSExample.CountDownLatchExampleTimeOutTest - 0-1559271362541
10:56:02.548 [pool-1-thread-9] INFO AQSExample.CountDownLatchExampleTimeOutTest - 8-1559271362548
10:56:02.548 [main] INFO AQSExample.CountDownLatchExampleTimeOutTest - 执行完毕,1559271362441-1559271362548

The results can be seen, all the threads before the thread is finished emperor print "is finished."

2. timeout block all threads of execution, after which time the direct release.

If we set the timeout after

@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());
    }
}

Because each thread after a delay of 50 milliseconds and then executed, count has timed a priority so print out the results of the completed execution. Then proceed to the content of thread.

结果
11:14:55.509 [main] INFO AQSExample.CountDownLatchExampleTimeOutTest - 执行完毕,1559272495373-1559272495506
11:14:55.542 [pool-1-thread-1] INFO AQSExample.CountDownLatchExampleTimeOutTest - 0-1559272495542
11:14:55.542 [pool-1-thread-2] INFO AQSExample.CountDownLatchExampleTimeOutTest - 1-1559272495542
11:14:55.543 [pool-1-thread-3] INFO AQSExample.CountDownLatchExampleTimeOutTest - 2-1559272495543
11:14:55.543 [pool-1-thread-4] INFO AQSExample.CountDownLatchExampleTimeOutTest - 3-1559272495543
11:14:55.543 [pool-1-thread-5] INFO AQSExample.CountDownLatchExampleTimeOutTest - 4-1559272495543
11:14:55.544 [pool-1-thread-6] INFO AQSExample.CountDownLatchExampleTimeOutTest - 5-1559272495544
11:14:55.544 [pool-1-thread-7] INFO AQSExample.CountDownLatchExampleTimeOutTest - 6-1559272495544
11:14:55.545 [pool-1-thread-9] INFO AQSExample.CountDownLatchExampleTimeOutTest - 8-1559272495545
11:14:55.545 [pool-1-thread-8] INFO AQSExample.CountDownLatchExampleTimeOutTest - 7-1559272495545
11:14:55.545 [pool-1-thread-10] INFO AQSExample.CountDownLatchExampleTimeOutTest - 9-1559272495545

CountDownLatch source parsing

CountDownLatch source of methods and properties are not many, let's look at each resolution.

And a frame construction method 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 () method parses

This method is used after the implementation of the thread count minus the number of statistics,

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

3.await () method parses

//拦截主线程的方法。主线程在这里等待条件达成后继续执行。
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 problem

CountDownLatch counter can not be completely reset, you need to recreate the complete use CountdownLatch to the next round of obstruction. The follow-up tools have the tools to solve this problem,

CountDownLatch summary

CountDownLatch This class enables a thread waiting for other threads to complete their work before execution. Cheng has a non-useful results in terms of uniform dispersion calculation result of synthesis, a process by loading resources. Next we explain to reset the counter at the latch tool CyclicBarrier.

Guess you like

Origin www.cnblogs.com/yanlong300/p/10954848.html