JUC并发包基本使用
一、简介
传统的Java多线程开发中,wait、notify、synchronized等如果不注意使用的话,很容易引起死锁、脏读问题。Java1.5 版本开始增加 java.util.concurrent 并发编程包,简化了多线程开发难度。添加了很多的多线程操作工具类,可根据实际需求去选择使用。
JUC 常用工具类:
Semaphore - 信号量
ReentrantLock - 可重入锁。之前有做过简介使用,详见 https://www.cnblogs.com/eric-fang/p/8991208.html
ReadWriteLock - 读写锁
BlockingQueue - 阻塞队列。详见 https://www.cnblogs.com/eric-fang/p/8989860.html
CountDownLatch - 计数器。在计数器归零后,允许之前阻塞的若干线程继续执行
CyclicBarrier - 栅栏。在某一条件达成之前,所有线程均阻塞等待
AtomicXXXXXXX - 原子操作类,常见的有:AtomicInteger、AtomicLong、AtomicBoolean。
TimeUnit - 时间枚举类,提供一些时间的便捷操作
Executor、ExecutorService、Future : 之前有做过简介使用,详见 https://www.cnblogs.com/eric-fang/p/9004020.html
二、使用
2.1、信号量Semaphore
一般用于限定同时访问操作的线程数量。例如:有时候可以很好的限制公共资源的使用,例如如果开启几十个线程去读取一些文件,然后读取到的数据需要入库的话,由于数据库的连接资源是稀缺资源,可能远小于读取文件的线程数,这时候可以利用信号量去限制每次并发获取数据库连接资源的线程数。
如下示例代码,虽然同时有10个线程执行,但是只能允许2个线程的并发执行。
package com.cfang.prebo.thread; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @Slf4j
public class TestSemaphore2 { private static Semaphore semaphore = new Semaphore(); private static ExecutorService executorService = Executors.newFixedThreadPool(); public static void main(String[] args) {
for(int i = ; i < ; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
//申请通行证
semaphore.acquire();
// 模拟业务逻辑
TimeUnit.SECONDS.sleep();
log.info("{} 处理完成", Thread.currentThread().getName());
//释放通行证
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
}
}
2.2、计数器CountDownLatch
同步计数器,构造方法传值,用来限定计数器的次数。
countDown方法每次调用,计数器值减 1。CountDownLatch会一直阻塞着调用await方法的线程,直到计数器值变为0。
package com.cfang.prebo.thread; import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; @Slf4j
public class TestCountDownLatch { private static CountDownLatch countDownLatch = new CountDownLatch(); private static AtomicInteger integerVal = new AtomicInteger(); public static void main(String[] args) throws Exception{
for(int i = ; i < ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
//业务处理逻辑
try {
int size = new Random().nextInt();
integerVal.getAndAdd(size);
TimeUnit.SECONDS.sleep();
log.info("{} 处理完成,{}", Thread.currentThread().getName(), size);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}, "thread-" + i).start();
}
String threadName = Thread.currentThread().getName();
log.info("{} thread waiting...", threadName);
countDownLatch.await();
log.info("{} doing, value: {}",threadName, integerVal.get());
} }
2.3、栅栏CyclicBarrier
栅栏屏障,构造方法传值来设定一个阈值。线程调用 await 方法的时候,线程就会被阻塞。当阻塞的线程数达到阈值的时候,所有阻塞线程全部放行。可重置重复使用。
package com.cfang.prebo.thread; import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; @Slf4j
public class TestCyclicBarrier implements Runnable{ private CyclicBarrier barrier = new CyclicBarrier(, this); private static AtomicInteger integerVal = new AtomicInteger(); public void count() {
for(int i = ; i < ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
//业务处理逻辑
try {
int size = new Random().nextInt();
integerVal.getAndAdd(size);
TimeUnit.SECONDS.sleep();
log.info("{} 处理完成,{}", Thread.currentThread().getName(), size);
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "thread-" + i).start();
}
} @Override
public void run() {
//业务逻辑处理完成后调用
log.info("{} 统计完成,{}", Thread.currentThread().getName(), integerVal.get());
} public static void main(String[] args) {
TestCyclicBarrier testCyclicBarrier = new TestCyclicBarrier();
testCyclicBarrier.count();
}
}
JUC并发包基本使用的更多相关文章
- JUC并发包与容器类 - 面试题(一网打净,持续更新)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- 聊聊 JUC 并发包
今天开始我们聊聊 Java 并发工具包中提供的一些工具类,本文主要从并发同步容器和并发集合工具角度入手,简单介绍下相关 API 的用法与部分实现原理,旨在帮助大家更好的使用和理解 JUC 工具类. 在 ...
- JUC并发包学习
1.什么是JUC java.util工具包.包.分类 业务:普通的线程代码 Thread Runable:没有返回值.效率相对于Callable相对较低. 2.线程和进程 进程:一个程序.如:QQ.e ...
- JUC——并发集合类
如果要进行多个数据的保存,无疑首选类集(List.Set.Queue.Map),在类集的学习的时候也知道一个概念:许多集合的子类都具有同步与异步的差别,但是如果真的要在多线程之中去使用这些类,是否真的 ...
- 并发包学习(三)-AbstractQueuedSynchronizer总结
J.U.C学习的第二篇AQS.AQS在Java并发包中的重要性,毋庸置疑,所以单独拿出来理一理.本文参考总结自<Java并发编程的艺术>第五章第二节队列同步器. 什么是AbstractQu ...
- JUC——JUC开发简介(一)
前言 JUC是Java5.0开始提供的一组专门实现多线程并发处理的开发框架,利用JUC开发架构可以有效的解决实际线程项目开发之中出现的死锁.阻塞.资源访问与公平机制. 此笔记主要记录java.util ...
- Java并发包——线程通信
Java并发包——线程通信 摘要:本文主要学习了Java并发包里有关线程通信的一些知识. 部分内容来自以下博客: https://www.cnblogs.com/skywang12345/p/3496 ...
- J.U.C并发包(1)
J.U.C并发包(1) AbstractQueuedSynchronizer AbstractQueuedSynchronizer是JUC并发包中锁的底层支持,AbstractQueuedSynchr ...
- java架构之路(多线程)JUC并发编程之Semaphore信号量、CountDownLatch、CyclicBarrier栅栏、Executors线程池
上期回顾: 上次博客我们主要说了我们juc并发包下面的ReetrantLock的一些简单使用和底层的原理,是如何实现公平锁.非公平锁的.内部的双向链表到底是什么意思,prev和next到底是什么,为什 ...
随机推荐
- ESP8266-12F
读者可以把ESP8266当做Arduino+WiFi功能来开发 ESP8266模块支持STA/AP/STA+AP 三种工作模式: STA 模式:ESP8266模块通过路由器连接互联网,手机或电脑通过互 ...
- MySQL把多条数据给汇总成一条数据
用到的是这个函数: group_concat() select group_buying_id, group_concat(app_user_ids) from org_user_group grou ...
- Codeforces 864E - Fire(dp)
原题连接:http://codeforces.com/problemset/problem/864/E 题意:一个人想从大火中带走一些东西.每次他只能带一个,耗时ti ,价值为pi, 当总时间超过di ...
- C++STL手写版
手写STL,卡常专用. node为变量类型,可以自由定义,以下不再赘述. 1.stack(栈) 开一个数组,和一个top指针,压栈时++,弹栈时--即可. struct stack{ int tp;n ...
- JSP Cookies处理
JSP Cookies处理 Cookies是存储在客户机的文本文件,它们保存了大量轨迹信息.在servlet技术基础上,JSP显然能够提供对HTTP cookies的支持. 通常有三个步骤来识别回头客 ...
- 3D Computer Grapihcs Using OpenGL - 06 Vertex and Fragment Shaders
从这里就接触到了可编程图形渲染管线. 下面介绍使用Vertex Shader (顶点着色器)和 Fragment Shader(像素着色器)的方法. 我们的目标是使用这两个着色器给三角形填充绿色. 添 ...
- 动态GI
在Engine/Config 目录中找到ConsoleVariables.ini并打开,在其中加入 r.LightPropagationVolume = 1 ,保存,重启引擎 如果场景中有Post P ...
- POJ 1383 Labyrinth (bfs 树的直径)
Labyrinth 题目链接: http://acm.hust.edu.cn/vjudge/contest/130510#problem/E Description The northern part ...
- 5.React中组件通信问题
1.父组件传递值给子组件 想必这种大家都是知道的吧!都想到了用我们react中的props,那么我在这简单的写了小demo,请看父组件 class Parent extends Component{ ...
- oracle体系结构基础
摘自:http://jianshi-dlw.iteye.com/blog/1554892 Oracle的体系结构大体上分为两部分:Instance(实例)和Database(数据库). Instanc ...