Java并发编程之闭锁与栅栏的实现

一、前言

闭锁与栅栏是在多线程编程中的概念,因为在多线程中,我们不能控制线程的执行状态,所以给线程加锁,让其按照我们的想法有秩序的执行。

闭锁

CountDownLatch,实例化时需要传入一个int类型的数字(count),意为等待count个线程完成之后才能执行下一步动作。

如今天要做的事情是吃晚饭,再去散步。假设11个人相约晚饭后一起去散步,我们得等11个人全都吃完晚饭了才能出发去散步。简而言之就是做了才到达某一种状态。

栅栏

CyclicBarrier,实例化时需要传入一个int类型的数字(parties),意为等待parties个线程都准备就绪后才能执行自己的任务。

如今天要做的事情是吃晚饭,8个人约好一起去某餐厅吃饭,得等到人齐了才能去吃饭。简而言之就是到达某种状态后一起做。

二、实例

闭锁 CountDownLatch

package com.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;

public class Test {
 public static void main(String[] args) {
 CountDownLatch latch = new CountDownLatch(3);

        // 模拟三个任务
 List<String> jobs = new ArrayList<String>();
 jobs.add("first");
 jobs.add("second");
 jobs.add("third");

        // 循环执行任务
 for (String job : jobs) {
  new Thread(new Runnable() {

  @Override
  public void run() {
   System.out.println(Thread.currentThread().getName() + " : 进入run方法");
   latch.countDown();
   System.out.println(Thread.currentThread().getName() + " : 执行" + job);
  }
  }).start();
 }

 try {
  latch.await();
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 // 任务都执行完后才执行
 System.out.println("回到main线程");
 }

}

执行结果:

Thread-1 : 进入run方法

Thread-2 : 进入run方法

Thread-2 : 执行third

Thread-0 : 进入run方法

Thread-1 : 执行second

Thread-0 : 执行first

回到main线程

通过执行结果可看出,当所有线程都执行完后才能回到主线程继续执行后面的输出。

栅栏 CyclicBarrier

package com.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Test {
 public static void main(String[] args) {
 CyclicBarrier barrier = new CyclicBarrier(3);
 // 模拟创建三个任务
 List<String> jobs = new ArrayList<String>();
 jobs.add("first");
 jobs.add("second");
 jobs.add("third");
 //循环执行任务
 for (String job : jobs) {
  new Thread(new Runnable() {

  @Override
  public void run() {
   System.out.println(Thread.currentThread().getName() + " : 进入run方法");
   try {
   // 等待
   barrier.await();
   } catch (InterruptedException | BrokenBarrierException e) {
   e.printStackTrace();
   }
   System.out.println(Thread.currentThread().getName() + " : 执行" + job);
  }
  }).start();
 }
 }
}

执行结果:

Thread-1 : 进入run方法

Thread-2 : 进入run方法

Thread-0 : 进入run方法

Thread-0 : 执行first

Thread-1 : 执行second

Thread-2 : 执行third

通过执行结果可看出,当所有线程都执行都进入到run方法后,才能继续执行自己内部的方法。

到此这篇关于Java并发编程之闭锁与栅栏的实现的文章就介绍到这了,更多相关Java 闭锁与栅栏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java并发编程之栅栏(CyclicBarrier)实例介绍

    栅栏类似闭锁,但是它们是有区别的. 1.闭锁用来等待事件,而栅栏用于等待其他线程.什么意思呢?就是说闭锁用来等待的事件就是countDown事件,只有该countDown事件执行后所有之前在等待的线程才有可能继续执行;而栅栏没有类似countDown事件控制线程的执行,只有线程的await方法能控制等待的线程执行. 2.CyclicBarrier强调的是n个线程,大家相互等待,只要有一个没完成,所有人都得等着. 场景分析:10个人去春游,规定达到一个地点后才能继续前行.代码如下 复制代码 代码如

  • 实例讲解Java并发编程之闭锁

    闭锁相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭着的,没有任何线程可以通过,当到达结束状态时,这扇门才会打开并容许所有线程通过.它可以使一个或多个线程等待一组事件发生.闭锁状态包括一个计数器,初始化为一个正式,正数表示需要等待的事件数量.countDown方法递减计数器,表示一个事件已经发生,而await方法等待计数器到达0,表示等待的事件已经发生.CountDownLatch强调的是一个线程(或多个)需要等待另外的n个线程干完某件事情之后才能继续执行. 场景应用: 10个运动员准备赛

  • Java并发编程之闭锁与栅栏的实现

    一.前言 闭锁与栅栏是在多线程编程中的概念,因为在多线程中,我们不能控制线程的执行状态,所以给线程加锁,让其按照我们的想法有秩序的执行. 闭锁 CountDownLatch,实例化时需要传入一个int类型的数字(count),意为等待count个线程完成之后才能执行下一步动作. 如今天要做的事情是吃晚饭,再去散步.假设11个人相约晚饭后一起去散步,我们得等11个人全都吃完晚饭了才能出发去散步.简而言之就是做了才到达某一种状态. 栅栏 CyclicBarrier,实例化时需要传入一个int类型的数

  • Java 并发编程:volatile的使用及其原理解析

    Java并发编程系列[未完]: •Java 并发编程:核心理论 •Java并发编程:Synchronized及其实现原理 •Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) •Java 并发编程:线程间的协作(wait/notify/sleep/yield/join) •Java 并发编程:volatile的使用及其原理 一.volatile的作用 在<Java并发编程:核心理论>一文中,我们已经提到过可见性.有序性及原子性问题,通常情况下我们可以通过Synchroniz

  • Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下是本文目录大纲: 一.CountDownLatch用法 二.CyclicBarrier用法 三.Semaphore用法 若有不正之处请多多谅解,并欢迎批评指正. 一.CountDownLatch

  • java并发编程_线程池的使用方法(详解)

    一.任务和执行策略之间的隐性耦合 Executor可以将任务的提交和任务的执行策略解耦 只有任务是同类型的且执行时间差别不大,才能发挥最大性能,否则,如将一些耗时长的任务和耗时短的任务放在一个线程池,除非线程池很大,否则会造成死锁等问题 1.线程饥饿死锁 类似于:将两个任务提交给一个单线程池,且两个任务之间相互依赖,一个任务等待另一个任务,则会发生死锁:表现为池不够 定义:某个任务必须等待池中其他任务的运行结果,有可能发生饥饿死锁 2.线程池大小 注意:线程池的大小还受其他的限制,如其他资源池:

  • Java并发编程之常用的辅助类详解

    1.CountDownLatch 1.2.示例:班长锁门问题 问题描述:假如有7个同学晚上上自习,钥匙在班长手上,并且要负责锁门.班长必须要等所有人都走光了,班长才能关灯锁门.这6个同学的顺序是无序的,不知道它们是何时离开.6个同学各上各的自习,中间没有交互.假如说6个学生是普通线程,班长是主线程,如何让主线程要等一堆线程运行完了,主线程才能运行完成呢. public class CountDownLatchDemo { public static void main(String[] args

  • Java并发编程Semaphore计数信号量详解

    Semaphore 是一个计数信号量,它的本质是一个共享锁.信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可:当信号量中有可用的许可时,线程能获取该许可:否则线程必须等待,直到有可用的许可为止. 线程可以通过release()来释放它所持有的信号量许可(用完信号量之后必须释放,不然其他线程可能会无法获取信号量). 简单示例: package me.socketthread; import java.util.concurrent.ExecutorService;

  • JAVA并发编程有界缓存的实现详解

    JAVA并发编程有界缓存的实现 1.有界缓存的基类 package cn.xf.cp.ch14; /** * *功能:有界缓存实现基类 *时间:下午2:20:00 *文件:BaseBoundedBuffer.java *@author Administrator * * @param <V> */ public class BaseBoundedBuffer<V> { private final V[] buf; private int tail; private int head

  • Java并发编程之重入锁与读写锁

    重入锁 重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁.重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞,该特性的实现需要解决以下两个问题. 1.线程再次获取锁.锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取. 2.锁的最终释放.线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁.锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放

  • Java并发编程(CyclicBarrier)实例详解

    Java并发编程(CyclicBarrier)实例详解 前言: 使用JAVA编写并发程序的时候,我们需要仔细去思考一下并发流程的控制,如何让各个线程之间协作完成某项工作.有时候,我们启动N个线程去做一件事情,只有当这N个线程都达到某一个临界点的时候,我们才能继续下面的工作,就是说如果这N个线程中的某一个线程先到达预先定义好的临界点,它必须等待其他N-1线程也到达这个临界点,接下来的工作才能继续,只要这N个线程中有1个线程没有到达所谓的临界点,其他线程就算抢先到达了临界点,也只能等待,只有所有这N

随机推荐