JUC学习笔记--JUC中并发工具类
JUC中并发工具类
CountDownLatch
CountDownLatch是我目前使用比较多的类,CountDownLatch初始化时会给定一个计数,然后每次调用countDown() 计数减1,
当计数未到达0之前调用await() 方法会阻塞直到计数减到0;
使用场景:多用于划分任务由多个线程执行,例如:最近写个豆瓣爬虫,需要爬取每个电影的前五页短评,可以划分成五个线程来处理数据。通过latch.await()保证全部完成再返回。
 public void latch() throws InterruptedException {
        int count= 5;
        CountDownLatch latch = new CountDownLatch(count);
        for (int x=0;x<count;x++){
            new Worker(x*20,latch).start();
        }
        latch.await();
        System.out.println("全部执行完毕");
    }
    class Worker extends Thread{
        Integer start;
        CountDownLatch latch;
        public Worker(Integer start,CountDownLatch latch){
            this.start=start;
            this.latch=latch;
        }
        @Override
        public void run() {
            System.out.println(start+" 已执行");
            latch.countDown();
        }
    }
/*
  20 已执行
  0 已执行
  40 已执行
  60 已执行
  80 已执行
  全部执行完毕
*/
CyclicBarrier
它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)也就是阻塞在调用cyclicBarrier.await()的地方。
看上去CyclicBarrier 跟CountDownLatch 功能上类似,在官方doc上CountDownLatch的描述上就说明了,CountDownLatch 的计数无法被重置,
如果需要重置计数,请考虑使用CyclicBarrier。
CyclicBarrier初始时还可添加一个Runnable的参数, 此Runnable在CyclicBarrier的数目达到后,所有其它线程被唤醒前被最后一个进入 CyclicBarrier 的线程执行
使用场景:类似CyclicBarrier,但是 CyclicBarrier提供了几个countdownlatch 没有的方法以应付更复杂的场景,例如:
getNumberWaiting() 获取阻塞线程数量,
isBroken() 用来知道阻塞的线程是否被中断等方法。
reset() 将屏障重置为其初始状态。如果所有参与者目前都在屏障处等待,则它们将返回,同时抛出一个 BrokenBarrierException。
  public void latch() throws InterruptedException {
        int count = 5;
        CyclicBarrier cb = new CyclicBarrier(count, new Runnable() {
            @Override
            public void run() {
                System.out.println("全部执行完毕");
            }
        });
        ExecutorService executorService = Executors.newFixedThreadPool(count);
        while (true){
            for (int x=0;x<count;x++){
                executorService.execute(new Worker(x,cb));
            }
        }
    }
    class Worker extends Thread {
        Integer start;
        CyclicBarrier cyclicBarrier;
        public Worker(Integer start, CyclicBarrier cyclicBarrier) {
            this.start = start;
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            System.out.println(start + " 已执行");
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
/*
0 已执行
3 已执行
4 已执行
2 已执行
1 已执行
全部执行完毕
0 已执行
1 已执行
2 已执行
3 已执行
4 已执行
全部执行完毕
.....
*/
Semaphore
Semaphore 信号量维护了一个许可集,每次使用时执行acquire()从Semaphore获取许可,如果没有则会阻塞,每次使用完执行release()释放许可。
使用场景:Semaphore对用于对资源的控制,比如数据连接有限,使用Semaphore限制访问数据库的线程数。
    public void latch() throws InterruptedException, IOException {
        int count = 5;
        Semaphore semaphore = new Semaphore(1);
        ExecutorService executorService = Executors.newFixedThreadPool(count);
            for (int x=0;x<count;x++){
                executorService.execute(new Worker(x,semaphore));
            }
        System.in.read();
    }
    class Worker extends Thread {
        Integer start;
        Semaphore semaphore;
        public Worker(Integer start, Semaphore semaphore) {
            this.start = start;
            this.semaphore = semaphore;
        }
        @Override
        public void run() throws IllegalArgumentException {
            try {
                System.out.println(start + " 准备执行");
                TimeUnit.SECONDS.sleep(1);
                semaphore.acquire();
                System.out.println(start + " 已经执行");
                semaphore.release();
                System.out.println(start + " 已经释放");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
/*
0 准备执行
2 准备执行
1 准备执行
3 准备执行
4 准备执行
2 已经执行
2 已经释放
4 已经执行
4 已经释放
1 已经执行
1 已经释放
0 已经执行
0 已经释放
3 已经执行
3 已经释放
*/
Exchanger
Exchanger 用于两个线程间的数据交换,它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。
使用场景: 两个线程相互等待处理结果并进行数据传递。
    public void latch() throws InterruptedException, IOException {
        int count = 5;
        Exchanger<String> exchanger = new Exchanger<>();
        ExecutorService executorService = Executors.newFixedThreadPool(count);
            for (int x=0;x<count;x++){
                executorService.execute(new Worker(x,exchanger));
            }
        System.in.read();
    }
    class Worker extends Thread {
        Integer start;
        Exchanger<String>  exchanger;
        public Worker(Integer start, Exchanger<String> exchanger) {
            this.start = start;
            this.exchanger = exchanger;
        }
        @Override
        public void run() throws IllegalArgumentException {
            try {
                System.out.println(Thread.currentThread().getName() + " 准备执行");
                TimeUnit.SECONDS.sleep(start);
                System.out.println(Thread.currentThread().getName() + " 等待交换");
                String value = exchanger.exchange(Thread.currentThread().getName());
                System.out.println(Thread.currentThread().getName() + " 交换得到数据为:"+value);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
/*
pool-1-thread-1 准备执行
pool-1-thread-1 等待交换
pool-1-thread-3 准备执行
pool-1-thread-2 准备执行
pool-1-thread-5 准备执行
pool-1-thread-4 准备执行
pool-1-thread-2 等待交换
pool-1-thread-1 交换得到数据为:pool-1-thread-2
pool-1-thread-2 交换得到数据为:pool-1-thread-1
pool-1-thread-3 等待交换
pool-1-thread-4 等待交换
pool-1-thread-4 交换得到数据为:pool-1-thread-3
pool-1-thread-3 交换得到数据为:pool-1-thread-4
pool-1-thread-5 等待交换
*/
Exchanger必须成对出现,否则会像上面代码执行结果那样,pool-1-thread-5一直阻塞等待与其交换数据的线程,为了避免这一现象,可以使用exchange(V x, long timeout, TimeUnit unit)设置最大等待时长
JUC学习笔记--JUC中并发工具类的更多相关文章
- 多线程学习笔记六之并发工具类CountDownLatch和CyclicBarrier
		
目录 简介 CountDownLatch 示例 实现分析 CountDownLatch与Thread.join() CyclicBarrier 实现分析 CountDownLatch和CyclicBa ...
 - java学习笔记37(sql工具类:JDBCUtils)
		
在之前的内容中,我们发现,当我们执行一条语句时,每新建一个方法,就要重新连接一次数据库,代码重复率很高,那么能不能把这些重复代码封装成一个类呢,我们学习方法时,就学习到方法就是为了提高代码的利用率,所 ...
 - Java学习笔记49(DBUtils工具类二)
		
上一篇文章是我们自己模拟的DBUtils工具类,其实有开发好的工具类 这里使用commons-dbutils-1.6.jar 事务的简单介绍: 在数据库中应用事务处理案例:转账案例 张三和李四都有有自 ...
 - Java学习笔记48(DBUtils工具类一)
		
上一篇的例子可以明显看出,在增删改查的时候,很多的代码都是重复的, 那么,是否可以将增删改查封装成一个类,方便使用者 package demo; /* * 实现JDBC的工具类 * 定义方法,直接返回 ...
 - ReactiveX 学习笔记(9)工具类操作符
		
Observable Utility Operators 本文的主题为处理 Observable 的实用工具类操作符. 这里的 Observable 实质上是可观察的数据流. RxJava操作符(六) ...
 - [ 原创 ]学习笔记-Android 中关于Cursor类的介绍
		
此博文转载自:http://www.cnblogs.com/TerryBlog/archive/2010/07/05/1771459.html 主讲Cursor的用法 使用过 SQLite 数据库的童 ...
 - Java学习笔记-Java中的常用类
		
Java中有很多类是很常用的,此处列举System,Runtime,Date,Calendar,Math System System:类中的方法和属性都是静态的 字段摘要 static PrintSt ...
 - JUC 常用4大并发工具类
		
什么是JUC? JUC就是java.util.concurrent包,这个包俗称JUC,里面都是解决并发问题的一些东西 该包的位置位于java下面的rt.jar包下面 4大常用并发工具类: Count ...
 - Java并发多线程 - 并发工具类JUC
		
安全共享对象策略 1.线程限制 : 一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改 2.共享只读 : 一个共享只读的对象,在没有额外同步的情况下,可以被多个线程并发访问, 但是任何线程都 ...
 
随机推荐
- 安卓图表引擎AChartEngine(六) - 框架源码结构图
			
包结构: org.achartengine: org.achartengine.model: org.achartengine.renderer: org.achartengine.tools: 安卓 ...
 - js 中调用 Object.prototype.toString()来检测对象的类型
			
1.使用toString()方法来检测对象类型 可以通过toString() 来获取每个对象的类型.为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Fun ...
 - ural1553 Caves and Tunnels
			
Caves and Tunnels Time limit: 3.0 secondMemory limit: 64 MB After landing on Mars surface, scientist ...
 - 基于css3的环形动态进度条(原创)
			
基于css3实现的环形动态加载条,也用到了jquery.当时的想法是通过两个半圆的转动,来实现相应的效果,其实用css3的animation也可以实现这种效果.之所以用jquery是因为通过jquer ...
 - (简单) POJ 3254 Corn Fields,状压DP。
			
Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; ...
 - [Unity Asset]AssetBundle系列——游戏资源打包
			
转载:http://www.cnblogs.com/sifenkesi/p/3557231.html 将本地资源打包,然后放到资源服务器上供游戏客户端下载或更新.服务器上包含以下资源列表:(1)游戏内 ...
 - pom文件说明
			
http://www.blogjava.net/hellxoul/archive/2013/05/16/399345.html
 - Android线程之异步消息处理机制(二)——Message、Handler、MessageQueue和Looper
			
异步消息处理机制解析 Android中的异步消息处理主要有四个部分组成,Message.Handler.MessageQueue和Looper. 1.Message Message是在线程之间传递的消 ...
 - Android小功能之垂直滚动条
			
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android=" ...
 - S3C2440触摸屏驱动详解
			
2440的触摸屏转换接口搭载在ADC接口之上,使用上比ADC接口多了一些花样,首先,触摸屏接口有几种转换模式 1. 普通转换模式 单转换模式是最合适的通用ADC转换.此模式可以通过设置ADCCON(A ...