博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
阅读量:6330 次
发布时间:2019-06-22

本文共 5410 字,大约阅读时间需要 18 分钟。

前言

JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch、CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行介绍。

CountDownLatch

CountDownLatch的主要作用是利用计数来保证线程的执行顺序(我自己的理解),有点像倒计时,当计数为0时某个线程才能开始执行。

CountDownLatch的主要方法很简单易用,包括:

  • CountDownLatch(int count) : 构造方法,需要传入计数的初始值
  • void await() : 调用者线程会被挂起,直到计数为0时才能执行
  • boolean await(long timeout, TimeUnit unit) : 同上,但是加入了超时参数,如果超时了计数还不为0,也会照样执行,避免了一直阻塞
  • void countDown() : 计数减一

示例代码:CountDownLatchTest.java

package juc.util;import java.util.concurrent.CountDownLatch;/** * Created by puyangsky on 2017/1/7. */public class CountDownLatchTest {    public static void main(String[] args) {        final CountDownLatch latch = new CountDownLatch(2);                //用了匿名类创建线程        new Thread() {            public void run() {                try {                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");                    Thread.sleep(2000);                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");                    latch.countDown();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }.start();        new Thread() {            public void run() {                try {                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");                    Thread.sleep(2000);                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");                    latch.countDown();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }.start();        System.out.println("主线程"+Thread.currentThread().getName()+"正在执行");        try {            latch.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("主线程"+Thread.currentThread().getName()+"执行完毕");    }}

结果:

主线程main正在执行子线程Thread-0正在执行子线程Thread-1正在执行子线程Thread-0执行完毕子线程Thread-1执行完毕主线程main执行完毕

可以从结果中看到主线程本来是最先执行完,结果需要等两个子线程执行完才结束,就是因为调用了await方法。

CyclicBarrier

CyclicBarrier的意思是回环栅栏,作用是让一组线程同时到达某个时间节点。提供的重要方法如下:

  • CyclicBarrier(int parties) : 构造方法,传入线程组的数量
  • CyclicBarrier(int parties, Runnable barrierAction) : 构造方法,传入线程组的数量和当线程达到时间节点后要做的操作(由其中的某一个线程去执行)
  • int await() : 挂起当前线程,直到所有线程组中的线程都完成后继续执行,返回当前线程到达的次序
  • int await(long timeout, TimeUnit unit) : 加了一个超时参数

示例代码 CyclicBarrierTest.java:

package juc.util;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * Created by puyangsky on 2017/1/7. */public class CyclicBarrierTest {    public static void main(String[] args) {        CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {            @Override            public void run() {                System.out.println("当前线程"+Thread.currentThread().getName());            }        });        for (int i=0;i<5;i++) {            new Task(barrier).start();        }    }    static class Task extends Thread {        private CyclicBarrier barrier;        public Task(CyclicBarrier barrier) {            this.barrier = barrier;        }        public void run() {            System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");            try {                Thread.sleep(3000);                System.out.println("子线程"+Thread.currentThread().getName()+"执行完成");                barrier.await();            } catch (InterruptedException e) {                e.printStackTrace();            } catch (BrokenBarrierException e) {                e.printStackTrace();            }            System.out.println("全部线程执行完成");        }    }}

结果:

子线程Thread-0正在执行子线程Thread-3正在执行子线程Thread-2正在执行子线程Thread-1正在执行子线程Thread-4正在执行子线程Thread-3执行完成子线程Thread-2执行完成子线程Thread-0执行完成子线程Thread-1执行完成子线程Thread-4执行完成当前线程Thread-4全部线程执行完成全部线程执行完成全部线程执行完成全部线程执行完成全部线程执行完成

可以看到这一组线程是同步的去执行的。

Semaphore

Semaphore的意思是信号量,其作用是提供一个许可范围,只有获得了许可才能继续执行。

  • Semaphore(int permits):构造方法,需要传入许可数
  • Semaphore(int permits, boolean fair):fair为true时使用公平锁,false时使用非公平锁,具体在介绍AQS时讲解
  • void acquire():获得许可,可中断
  • void acquireUninterruptibly():不可中断的获取
  • void release():释放许可

示例 SemaphoreTest.java

package juc.util;import java.util.concurrent.Semaphore;/** * Created by puyangsky on 2017/1/7. */public class SemaphoreTest {    public static void main(String[] args) {        Semaphore semaphore = new Semaphore(5);        for (int i = 0;i < 10;i++) {            new Worker(i, semaphore).start();        }    }    static class Worker extends Thread {        private Semaphore semaphore;        private int num;        public Worker(int num, Semaphore semaphore) {            this.semaphore = semaphore;            this.num = num;        }        public void run() {            try {                semaphore.acquire();                System.out.println("工人" + (this.num + 1) + "占用一个机器在生产...");                Thread.sleep(2000);                System.out.println("工人" + (this.num + 1) + "释放一个机器...");                semaphore.release();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

结果

工人1占用一个机器在生产...工人3占用一个机器在生产...工人4占用一个机器在生产...工人5占用一个机器在生产...工人7占用一个机器在生产...工人1释放一个机器...工人5释放一个机器...工人4释放一个机器...工人7释放一个机器...工人3释放一个机器...工人8占用一个机器在生产...工人9占用一个机器在生产...工人10占用一个机器在生产...工人6占用一个机器在生产...工人2占用一个机器在生产...工人9释放一个机器...工人6释放一个机器...工人10释放一个机器...工人8释放一个机器...工人2释放一个机器...

可以看到每次只有五个线程能运行,其他线程只有等待这五个线程释放许可后才能运行。

参考文章:

  • jdk1.7

转载于:https://www.cnblogs.com/puyangsky/p/6260404.html

你可能感兴趣的文章
初心大陆-----python宝典 第五章之列表
查看>>
java基础学习2
查看>>
sysbench使用笔记
查看>>
有关电子商务信息的介绍
查看>>
NFC·(近距离无线通讯技术)
查看>>
nginx 禁止某个IP访问立网站的设置方法
查看>>
多线程基础(三)NSThread基础
查看>>
PHP的学习--Traits新特性
查看>>
ubuntu下,py2,py3共存,/usr/bin/python: No module named virtualenvwrapper错误解决方法
查看>>
Ext.form.field.Number numberfield
查看>>
异地多活数据中心项目
查看>>
Linux文件夹分析
查看>>
解决部分月份绩效无法显示的问题:timestamp\union al\autocommit等的用法
查看>>
CRT + lrzsz 进行远程linux系统服务器文件上传下载
查看>>
nginx 域名跳转 Nginx跳转自动到带www域名规则配置、nginx多域名向主域名跳转
查看>>
man openstack >>1.txt
查看>>
linux几大服务器版本大比拼
查看>>
在BT5系统中安装postgresQL
查看>>
Can't connect to MySQL server on 'localhost'
查看>>
【Magedu】Week01
查看>>