美文网首页捞逼205文集。
并发(5) - concurrent包构件

并发(5) - concurrent包构件

作者: 黑色偏幽默 | 来源:发表于2017-11-03 16:42 被阅读15次

    java.util.concurrent 中的构件

    CountDownLatch

    CountDownLatch 被用于同步一个或多个任务,强制它们等待一组任务的操作。

    public class Main {
       static final int SIZE = 10;
    
       public static void main(String[] args) throws InterruptedException, IOException {
    
           ExecutorService exec = Executors.newCachedThreadPool();
           CountDownLatch latch = new CountDownLatch(SIZE);
           int count = 10;
           while (count-- > 0) {
               exec.execute(() -> {
                   try {
                       TimeUnit.MILLISECONDS.sleep(100);
                       System.out.println("one task was finished");
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   } finally {
                       latch.countDown();
                   }
               });
           }
           exec.execute(() -> {
               try {
                   latch.await();
                   System.out.println("submit tasks report");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           });
           TimeUnit.MILLISECONDS.sleep(4000);
           exec.shutdownNow();
       }
    
    }
    

    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    one task was finished
    submit tasks report

    任何在 CountDownLatch 对象上调用 await() 方法的任务都将阻塞,直到这个 latch 计数为 0。
    CountDownLatch 被设计为只能使用一次,不能重置计数器的值。

    CyclicBarrier

    可以多次重用的 CountDownLatch

    public class Main {
    
       private static final int SIZE = 10;
       private static Random random = new Random(47);
    
       public static void main(String[] args) throws InterruptedException, IOException {
    
           ExecutorService exec = Executors.newCachedThreadPool();
           CyclicBarrier barrier = new CyclicBarrier(SIZE, () -> System.out.println("submit tasks report"));
           int count = 10;
           while (count-- > 0){
               exec.execute(() -> {
                   try {
                       TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
                       System.out.println("one task was finished");
                       barrier.await();
                   } catch (InterruptedException | BrokenBarrierException e) {
                       e.printStackTrace();
                   }
               });
           }
           TimeUnit.MILLISECONDS.sleep(4000);
           exec.shutdownNow();
       }
    
    }
    

    CyclicBarrier 对象所调用的 await() 次数,即等待这个资源而阻塞的线程数,达到这个构造器中设置的值时,将执行构造器中传入的Runnable() 方法,当我把 count 值改为 20 的时候,可以看到这个 "submit tasks report" 输出了 2 次,即达到我们要的效果。

    ScheduledExecutor

    使用 schedule() (运行一次任务) 或 scheduleAtFixedRate() (每隔规则的时间重复执行任务)。

    public class Main {
    
        private static final int SIZE = 5;
        private static Random random = new Random(47);
    
        public static void main(String[] args) throws InterruptedException, IOException {
            long start = System.currentTimeMillis();
            ScheduledExecutorService service = Executors.newScheduledThreadPool(SIZE);
            for (int i = 0; i < SIZE; i++) {
                service.schedule(() -> System.out.println(System.currentTimeMillis() - start),
                        random.nextInt(3000), TimeUnit.MILLISECONDS);
            }
            TimeUnit.SECONDS.sleep(5);
            service.shutdownNow();
        }
    }
    

    使用 ScheduledExecutor 区别于 Timer 的是,Timer 不会创建新的线程去执行这个任务,先前的任务的执行时间大于与下一个任务的间隔,会导致下一个任务推迟。

    相关文章

      网友评论

        本文标题:并发(5) - concurrent包构件

        本文链接:https://www.haomeiwen.com/subject/dqgtmxtx.html