java.util.current_Java基础知识-java.util.concurrent包下常见类的使用
一,Condition
一个场景,两个线程数数,同时启动两个线程,线程A数1、2、3,然后线程B数4、5、6,最后线程A数7、8、9,程序结束,这涉及到线程之间的通信。
public classConditionTest {static classNumberWrapper {public int value = 1;
}public static voidmain(String[] args) {//初始化可重入锁
final Lock lock = newReentrantLock();//第一个条件当屏幕上输出到3
final Condition reachThreeCondition =lock.newCondition();//第二个条件当屏幕上输出到6
final Condition reachSixCondition =lock.newCondition();//NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final//注意这里不要用Integer, Integer 是不可变对象
final NumberWrapper num = newNumberWrapper();//初始化A线程
Thread threadA = new Thread(newRunnable() {
@Overridepublic voidrun() {//需要先获得锁
lock.lock();
System.out.println("ThreadA获得lock");try{
System.out.println("threadA start write");//A线程先输出前3个数
while (num.value <= 3) {
System.out.println(num.value);
num.value++;
}//输出到3时要signal,告诉B线程可以开始了
reachThreeCondition.signal();
}finally{
lock.unlock();
System.out.println("ThreadA释放lock");
}
lock.lock();try{//等待输出6的条件
System.out.println("ThreadA获得lock");
reachSixCondition.await();
System.out.println("threadA start write");//输出剩余数字
while (num.value <= 9) {
System.out.println(num.value);
num.value++;
}
}catch(InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
System.out.println("ThreadA释放lock");
}
}
});
Thread threadB= new Thread(newRunnable() {
@Overridepublic voidrun() {try{
lock.lock();
System.out.println("ThreadB获得lock");
Thread.sleep(5000);//是await方法释放了锁
while (num.value <= 3) {//等待3输出完毕的信号
reachThreeCondition.await();
}
}catch(InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
System.out.println("ThreadB释放lock");
}try{
lock.lock();
System.out.println("ThreadB获得lock");//已经收到信号,开始输出4,5,6
System.out.println("threadB start write");while (num.value <= 6) {
System.out.println(num.value);
num.value++;
}//4,5,6输出完毕,告诉A线程6输出完了
reachSixCondition.signal();
}finally{
lock.unlock();
System.out.println("ThreadB释放lock");
}
}
});//启动两个线程
threadB.start();
threadA.start();
}
}
创建方式:通过Lock创建,Lock.newCondition();
常用方法:
await():阻塞,直到相同的Condition调用了signal方法。
signal():通知。
总结:Condition必须与Lock一起使用(wait()、notify()必须与synchronized一起使用,否则运行会报错java.lang.IllegalMonitorStateException),相比于wait与notify更加的灵活,可以设置各种情形,如上例中的到达3和到达6两个条件。
二,CountDownLatch
直接上代码:
public classCountDownLatchTest {public static voidmain(String[] args) {final CountDownLatch c = new CountDownLatch(3);//总数3
Thread t1 = new Thread(newRunnable(){
@Overridepublic voidrun() {try{
System.out.println("开始等");
c.await();//阻塞,等待countDown,当countDown到0就执行后面的完事了
System.out.println("完事");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2= new Thread(newRunnable(){
@Overridepublic voidrun() {for(int i=3;i>0;i--){
c.countDown();//减1
}
}
});
t1.start();
t2.start();
}
}
创建方式:直接创建,new CountDownLatch(int num);
常用方法:
await():阻塞,直到countDown方法被执行了num次。
countDown():减
总结:适用于一个线程等待其他线程的情景。
三,CyclicBarrier
通过代码思考一下与CountDownLatch的区别。
public classMainMission {privateCyclicBarrier barrier;private final static int threadCounts = 5;public voidrunMission() {
ExecutorService exec=Executors.newFixedThreadPool(threadCounts);//new 的时候要传入数字,我发现,这个类似semaphore,如果位置不足,线程会抢位置。数字要是threadCounts+1为主线程留一个位子,但实际测试中发现,只要等于threadCount就可以
barrier=new CyclicBarrier(threadCounts+1);for(int i=0;i<5;i++){
exec.execute(newMission(barrier));
}try{
barrier.await();
}catch(InterruptedException e) {
e.printStackTrace();
}catch(BrokenBarrierException e) {
e.printStackTrace();
}try{
Thread.sleep(1);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有任务都执行完了");
exec.shutdown();//如果不关闭,程序一直处于运行状态
}public static voidmain(String[] args) {
MainMission m= newMainMission();
m.runMission();
}
}class Mission implementsRunnable{privateCyclicBarrier barrier;publicMission(CyclicBarrier barrier){this.barrier =barrier;
}
@Overridepublic voidrun() {
System.out.println(Thread.currentThread().getName()+"开始执行任务");try{int sleepSecond = new Random().nextInt(10)*1000;
System.out.println(Thread.currentThread().getName()+"要执行"+sleepSecond+"秒任务");
Thread.sleep(sleepSecond);
}catch(InterruptedException e) {
e.printStackTrace();
}try{
barrier.await();
}catch(InterruptedException e) {
e.printStackTrace();
}catch(BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行完毕");
}
}
创建方式:直接创建,new CyclicBarrier(int num);
常用方法:
await():阻塞,直到阻塞的线程数量达到num个。
总结:想想一下百米跑,所有运动员都就位之后才会发令起跑,线程调用await意味着说,我准备好了。
四,Semaphore
下面是一个上厕所的例子,厕所位置有限,想用得排队了。实现使用的就是信号量,可以看出信号量可以用来做限流。
public class MySemaphore implementsRunnable{
Semaphore position;private intid;public MySemaphore(inti,Semaphore s){this.id=i;this.position=s;
}
@Overridepublic voidrun() {try{if(position.availablePermits()>0){
System.out.println("顾客["+this.id+"]进入厕所,有空位");
}else{
System.out.println("顾客["+this.id+"]进入厕所,没空位,排队");
}
position.acquire();//只有在acquire之后才能真正的获得了position
System.out.println("#########顾客["+this.id+"]获得坑位");
Thread.sleep((int)(Math.random()*100000));
System.out.println("@@@@@@@@@顾客["+this.id+"]使用完毕");
position.release();
}catch(Exception e){
e.printStackTrace();
}
}public static voidmain(String args[]){
ExecutorService list=Executors.newCachedThreadPool();
Semaphore position=new Semaphore(2);for(int i=0;i<10;i++){
list.submit(new MySemaphore(i+1,position));
}
list.shutdown();
position.acquireUninterruptibly(2);
System.out.println("使用完毕,需要清扫了");
position.release(2);
}
}
创建方式:直接创建,new Semaphore(int num);
常用方法:
availablePermits():看现在可用的信号量。
acquire():尝试获取一个位置,如果获取不到则阻塞。
release():释放位置。
acquireUninterruptibly(int num):尝试获取num个许可,如果没有足够的许可则阻塞,一直阻塞到有足够的许可释放出来。调用这个方法的线程具有优先获取许可的权利。如果调用线程被interrupted,该线程并不会被打断,它会继续阻塞等待许可。
总结:抢位置。
五,ReentrantLock
创建方式:
new ReentrantLock(); 此种创建方式会创建出一个非公平锁。
new ReentrantLock(true); 此种方式会创建出一个公平锁。
非公平锁:当锁处于无线程占有的状态,此时其他线程和在队列中等待的线程都可以抢占该锁。
公平锁:当锁处于无线程占有的状态,在其他线程抢占该锁的时候,都需要先进入队列中等待。
tryLock()方法:尝试去获取锁,如果没有获取到直接返回,不等待。
六,ReentrantReadWriteLock
创建方式:new ReentrantReadWriteLock();
常用方法:
readLock().lock();写锁
writeLock().lock();读锁
readLock().unlock();解锁
writeLock().unlock();解锁
总结:
* 如果目前是读锁,其他读锁也可以进请求,写锁不能进。
* 如果目前是写锁,那么其他所有的锁都不可以进。
*适用于读多写少的情况,如果是写多读少用ReentrantLock。
七,Callable接口
*Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
与Runnable对比:
1.Callable可以有返回值,Runnable没有
2.Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
八,线程池
提供的线程池有几种:
//有数量限制的线程池
ExecutorService service=Executors.newFixedThreadPool(4);
//没有数量限制的线程池
ExecutorService service=Executors.newCachedThreadPool();
//单线程池
ExecutorService service=Executors.newSingleThreadExecutor();
他们都是通过下面这个线程池实现的
有数量线程池的实现方式
public static ExecutorService newFixedThreadPool(intnThreads) {return newThreadPoolExecutor(nThreads/*核心线程数*/, nThreads/*最高线程数*/,0L/*高出核心线程数的线程最高存活时间*/, TimeUnit.MILLISECONDS/*高出核心线程数的线程最高存活时间单位*/,new LinkedBlockingQueue()/*任务队列*/);
猜一猜剩下的两种线程池是怎么实现的。如果想自己实现,可以自己new
java.util.current_Java基础知识-java.util.concurrent包下常见类的使用相关推荐
- java.util 常见_Java基础知识-java.util.concurrent包下常见类的使用
一,Condition 一个场景,两个线程数数,同时启动两个线程,线程A数1.2.3,然后线程B数4.5.6,最后线程A数7.8.9,程序结束,这涉及到线程之间的通信. public classCon ...
- Java工具包工具类,java.util.concurrent 包下工具类的使用
CountDownLacth 的使用 常用于监听某些初始化操作,等初始化执行完毕,通知主线程继续执行. 先看示例代码: public class UseCountDownLatch { public ...
- 第76节:Java中的基础知识
第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...
- Java超详细基础知识
Java Java基础 编写第一个Java程序 alt+/可以对代码进行补充. package hello; public class Hello {public static void main(S ...
- Java核心技术卷一基础知识第10版demo实例
Java核心技术卷一基础知识第10版demo实例 第三章 JAVA的基本程序设计结构 3.7输入与输出 3.7.1读取输入 3.8控制流程 3.8.3循环 3.10数组 3.10.6多维数组 第四章 ...
- 4 万字超强总结!Java 这些必备基础知识不可少
点击「关注」公众号,回复"1024"获取2TB学习资源! 什么是Java Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概 ...
- Java原理性基础知识整理[详细]
文章目录 Java程序编译过程 编译型和解析型语言 命名规范 编程风格 大括号 非C风格的数组声明 阿里巴巴Java开发手册 On Java 8 Google Java 编程风格指南 基本数据类型 整 ...
- java学习笔记-基础知识-2023.3.29
学习网站:https://www.sxt.cn/Java_jQuery_in_action/History_Direction.html 刷题网站 牛客网专题-spring java sql 第一章 ...
- java 网络爬虫 正则表达式_【干货】Java网络爬虫基础知识
原标题:[干货]Java网络爬虫基础知识 引言 Java 网络爬虫具有很好的扩展性可伸缩性,其是目前搜索引擎开发的重要组成部分.例如,著名的网络爬虫工具 Nutch 便是采用 Java 开发,该工具以 ...
- java的一些基础知识(引用BlogJava 落花飞雪)
java的一些基础知识(引用BlogJava 落花飞雪) <Practical Java>笔记 1. 声明是什么? String s = "Hello world!" ...
最新文章
- fastjson jsonobject 转bean失败_烫发以后丑的不行?张柏芝、范冰冰、Angelababy也经历过的失败烫发造型回顾-非主流发型-发型站...
- qPCR实验疑难杂问解答
- 最大公约数(Greatest_Common_Divisor)
- nowcoder172C 保护 (倍增lca+dfs序+主席树)
- js 实现文件导出、文件下载
- 编译原理—词法分析器(Java)
- 微软CRM 2011 Beta 新功能之二:不同组织不同基本语言
- 数据结构——线性表的C语言实现
- (pytorch-深度学习系列)网络中的网络(NiN)
- 16进制编辑器 linux,Tweak - Linux下的16进制编辑器
- C# web调用控制台应用程序
- 新手从零学电脑组装与维修视频教程
- 【JAVA】每日练习——02
- 记一次爆破六位数密码(图书馆系统登录)
- QT5使用PCAN读取CAN数据
- 集合源码解析Map容器Gc回收算法
- OkHttp3使用介绍
- 华为服务器 电源管理 高性能,华为服务器可服务性设计介绍-电源篇-Huawei.PDF
- 如何在网页标题前添加图标
- 节拍器在学习音乐过程中起到什么作用?-小星星节拍器怎么样?