Java并发包下的几个API
并发包
(计数器)CountDownLatch
CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
import java.util.concurrent.CountDownLatch;
public class CountDownlatchTest {
public static void main(String[] args) {
CountDownLatch count = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始执行-->" + System.currentTimeMillis());
count.countDown();
System.out.println(Thread.currentThread().getName() + "结束执行-->" + System.currentTimeMillis());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始执行-->" + System.currentTimeMillis());
count.countDown();
System.out.println(Thread.currentThread().getName() + "结束执行-->" + System.currentTimeMillis());
}
}).start();
try {
count.await(); // 当Count减为0 时,执行后面的代码
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("两个子线程执行完毕....");
System.out.println("主线程继续执行.....");
for (int i = 0; i < 10; i++) {
System.out.println("main,i:" + i);
}
}
}
执行结果
Thread-0开始执行-->1564281731639
Thread-0结束执行-->1564281731639
Thread-1开始执行-->1564281731639
Thread-1结束执行-->1564281731639
两个子线程执行完毕....
主线程继续执行.....
main,i:0
main,i:1
main,i:2
main,i:3
main,i:4
main,i:5
main,i:6
main,i:7
main,i:8
main,i:9
(屏障)CyclicBarrier
CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
for (int i = 0; i < 5; i++) {
Writer writer = new Writer(cyclicBarrier);
writer.start();
}
}
}
class Writer extends Thread {
private CyclicBarrier cyc;
public Writer(CyclicBarrier cyc) {
this.cyc = cyc;
}
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + ",正在写入数据");
try {
Thread.sleep(3000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("线程" + Thread.currentThread().getName() + ",写入数据成功.....");
try {
cyc.await();
} catch (Exception e) {
}
System.out.println("所有线程执行完毕..........");
}
}
执行结果
线程Thread-0,正在写入数据
线程Thread-2,正在写入数据
线程Thread-1,正在写入数据
线程Thread-3,正在写入数据
线程Thread-4,正在写入数据
线程Thread-3,写入数据成功.....
线程Thread-1,写入数据成功.....
线程Thread-0,写入数据成功.....
线程Thread-2,写入数据成功.....
线程Thread-4,写入数据成功.....
所有线程执行完毕..........
所有线程执行完毕..........
所有线程执行完毕..........
所有线程执行完毕..........
所有线程执行完毕..........
(计数信号量)Semaphore
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。
Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:
semp.availablePermits()//函数用来获取当前可用的资源数量
semp.acquire(); //申请资源
semp.release();// 释放资源
// 创建一个计数阈值为5的信号量对象
// 只能5个线程同时访问
Semaphore semp = new Semaphore(5);
try {
// 申请许可
semp.acquire();
try {
// 业务逻辑
}catch (Exception e){
} finally {
// 释放许可
semp.release();
}
}catch(InterruptedException e){ }
案例:
需求:
一个商店只有3个抓娃娃机,但是有10个人要来抓娃娃,那怎么办?假设10的人的编号分别为1-10,并且1号先到,10号最后到。那么1-3号来的时候必然有可用抓娃娃机,可以开始抓娃娃,4号来的时候需要看看前面3人是否有人抓完了,如果有人抓完,4号就开始抓娃娃,否则等待。同样的道理,4-10号也需要等待正在抓娃娃的人抓完才能抓,并且谁先开始抓娃娃要看等待的人是否有素质,是否能遵守先来先用抓玩玩机的规则。
代码:
import java.util.Random;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semp = new Semaphore(3);
for (int i = 0; i <= 10; i++) {
CatchDollThread thread = new CatchDollThread("thread-" + i, semp);
thread.start();
}
}
}
class CatchDollThread extends Thread {
private String name;
private Semaphore cad;
public CatchDollThread(String name, Semaphore cad) {
this.name = name;
this.cad = cad;
}
@Override
public void run() {
int availablePermits = cad.availablePermits();
if (availablePermits > 0) {
System.out.println(this.name + "说: 有空闲的抓娃娃机");
} else {
System.out.println(this.name + "说: 没有空闲的娃娃机了");
}
try {
// 申请资源
cad.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.name + "开始抓娃娃" + ",此时空闲的机器:" + cad.availablePermits());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (Exception e) {
}
System.out.println(this.name + "抓完娃娃");
// 释放资源
cad.release();
}
}
执行结果
thread-1说: 有空闲的抓娃娃机
thread-3说: 有空闲的抓娃娃机
thread-2说: 有空闲的抓娃娃机
thread-0说: 有空闲的抓娃娃机
thread-4说: 没有空闲的娃娃机了
thread-2开始抓娃娃,此时空闲的机器:0
thread-3开始抓娃娃,此时空闲的机器:1
thread-1开始抓娃娃,此时空闲的机器:2
thread-5说: 没有空闲的娃娃机了
thread-6说: 没有空闲的娃娃机了
thread-7说: 没有空闲的娃娃机了
thread-8说: 没有空闲的娃娃机了
thread-9说: 没有空闲的娃娃机了
thread-10说: 没有空闲的娃娃机了
thread-1抓完娃娃
thread-0开始抓娃娃,此时空闲的机器:0
thread-3抓完娃娃
thread-4开始抓娃娃,此时空闲的机器:0
thread-4抓完娃娃
thread-5开始抓娃娃,此时空闲的机器:0
thread-0抓完娃娃
thread-6开始抓娃娃,此时空闲的机器:0
thread-2抓完娃娃
thread-7开始抓娃娃,此时空闲的机器:0
thread-6抓完娃娃
thread-8开始抓娃娃,此时空闲的机器:0
thread-5抓完娃娃
thread-9开始抓娃娃,此时空闲的机器:0
thread-8抓完娃娃
thread-10开始抓娃娃,此时空闲的机器:0
thread-10抓完娃娃
thread-7抓完娃娃
thread-9抓完娃娃
Java并发包下的几个API的更多相关文章
- Java并发包下锁学习第一篇:介绍及学习安排
Java并发包下锁学习第一篇:介绍及学习安排 在Java并发编程中,实现锁的方式有两种,分别是:可以使用同步锁(synchronized关键字的锁),还有lock接口下的锁.从今天起,凯哥将带领大家一 ...
- Java并发包下锁学习第二篇Java并发基础框架-队列同步器介绍
Java并发包下锁学习第二篇队列同步器 还记得在第一篇文章中,讲到的locks包下的类结果图吗?如下图: 从图中,我们可以看到AbstractQueuedSynchronizer这个类很重要(在本 ...
- Java基础(下)(JVM、API)
Java基础(下) 第三部分:Java源程序的编辑 我们知道,计算机是不能直接理解源代码中的高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序. 翻译 ...
- java并发包下的并发工具类
1.Exchanger 功能:用于线程间数据的交换 应用场景:1)遗传算法,目前还不是特别理解 2)校对工作,假设A,B线程做同一件任务,可以通过数据校验判断两线程是否正确的工作 例子:是一个简单的 ...
- 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)
问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...
- Java并发包——线程安全的Collection相关类
Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...
- Java并发包——Atomic操作
Java并发包——Atomic操作 摘要:本文主要学习了Java并发包下的atomic包中有关原子操作的一些类. 部分内容来自以下博客: https://blog.csdn.net/qq_303796 ...
- Java并发包——线程安全的Map相关类
Java并发包——线程安全的Map相关类 摘要:本文主要学习了Java并发包下线程安全的Map相关的类. 部分内容来自以下博客: https://blog.csdn.net/bill_xiang_/a ...
- paip.web数据绑定 下拉框的api设计 选择框 uapi python .net java swing jsf总结
paip.web数据绑定 下拉框的api设计 选择框 uapi python .net java swing jsf总结 ====总结: 数据绑定下拉框,Uapi 1.最好的是默认绑定..Map(k ...
随机推荐
- main方法中注入Spring bean
在有些情况下需要使用main使用Spring bean,但是main方法启动并没有托管给Spring管理,会导致bean失败,报空指针异常. 可以使用 ClassPathXmlApplicationC ...
- Netty服务端启动过程相关源码分析
1.Netty 是怎么创建服务端Channel的呢? 我们在使用ServerBootstrap.bind(端口)方法时,最终调用其父类AbstractBootstrap中的doBind方法,相关源码如 ...
- Java虚拟机详解(四)------垃圾收集器
上一篇博客我们介绍了Java虚拟机垃圾回收,介绍了几种常用的垃圾回收算法,包括标记-清除,标记整理,复制等,这些算法我们可以看做是内存回收的理论方法,那么在Java虚拟机中,由谁来具体实现这些方法呢? ...
- Keil5调试过程中遇到的一些警告和错误
最近用keil5调试代码出了一些警告与错误,整理如下: 1.warning: #1295-D: Deprecated declaration run_c - give arg types void r ...
- Iphone使用过程中遇到的问题
Q1:同一个Apple ID不同设备之间的通话记录保持同步 解决方法: Step1:"设置"--"电话"--"在其他设备上通话"--选择关闭 ...
- python 闭包,装饰器,random,os,sys,shutil,shelve,ConfigParser,hashlib模块
闭包 def make_arerage(): l1 = [] def average(price): l1.append(price) total = sum(l1) return total/len ...
- java优雅注释原则和代码格式列举
一.java的三种注释类型 单行注释:// ...... 块注释:/* ...... */ 文档注释:/** ...... */ 二.指导原则 注释不能美化糟糕的代码,碰到糟糕的代码就重新写吧. 用代 ...
- 7.19 包 logging模块 hashlib模块 openpyxl模块 深浅拷贝
包 包是什么 他是一系列文件的结合体,表现形式就是文件夹 包的本质还是模块 他通常会有__init__.py文件 我们首先回顾一下模块导入的过程 import module首次导入模块(.py文件) ...
- pycharm的补充
pycharm 快捷键 tab自动补全 首行缩进 ctrl+?是全行加#进行注释 ctrl+d 复制上一行 ctrl +z 撤销 ctrl+shift+z 撤销的撤销 更改字体大小
- sql server 日期近一年,同比
--近一年 ), , , ) SELECT CONVERT(VARCHAR, DATEADD(day, -DAY(GETDATE()), , ) --同比 ), , , ) SELECT CONVER ...