并发包

(计数器)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可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:

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的更多相关文章

  1. Java并发包下锁学习第一篇:介绍及学习安排

    Java并发包下锁学习第一篇:介绍及学习安排 在Java并发编程中,实现锁的方式有两种,分别是:可以使用同步锁(synchronized关键字的锁),还有lock接口下的锁.从今天起,凯哥将带领大家一 ...

  2. Java并发包下锁学习第二篇Java并发基础框架-队列同步器介绍

    Java并发包下锁学习第二篇队列同步器 还记得在第一篇文章中,讲到的locks包下的类结果图吗?如下图: ​ 从图中,我们可以看到AbstractQueuedSynchronizer这个类很重要(在本 ...

  3. Java基础(下)(JVM、API)

    Java基础(下) 第三部分:Java源程序的编辑 我们知道,计算机是不能直接理解源代码中的高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序. 翻译 ...

  4. java并发包下的并发工具类

    1.Exchanger 功能:用于线程间数据的交换 应用场景:1)遗传算法,目前还不是特别理解  2)校对工作,假设A,B线程做同一件任务,可以通过数据校验判断两线程是否正确的工作 例子:是一个简单的 ...

  5. 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)

    问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...

  6. Java并发包——线程安全的Collection相关类

    Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...

  7. Java并发包——Atomic操作

    Java并发包——Atomic操作 摘要:本文主要学习了Java并发包下的atomic包中有关原子操作的一些类. 部分内容来自以下博客: https://blog.csdn.net/qq_303796 ...

  8. Java并发包——线程安全的Map相关类

    Java并发包——线程安全的Map相关类 摘要:本文主要学习了Java并发包下线程安全的Map相关的类. 部分内容来自以下博客: https://blog.csdn.net/bill_xiang_/a ...

  9. paip.web数据绑定 下拉框的api设计 选择框 uapi python .net java swing jsf总结

    paip.web数据绑定 下拉框的api设计 选择框 uapi  python .net java swing jsf总结 ====总结: 数据绑定下拉框,Uapi 1.最好的是默认绑定..Map(k ...

随机推荐

  1. .net core web api部署到Linux系统CentOS 7

    一.创建一个.net core web api 的Demo 完成后的项目结构如图 修改下监听端口 发布代码 二.发布到CentOS 7上并运行 下一步需要一定的虚拟机知识了,我这里使用了windows ...

  2. Guava cache使用总结

    缓存分为本地缓存和远端缓存.常见的远端缓存有Redis,MongoDB:本地缓存一般使用map的方式保存在本地内存中.一般我们在业务中操作缓存,都会操作缓存和数据源两部分.如:put数据时,先插入DB ...

  3. Opengl_入门学习分享和记录_02_渲染管线(一)顶点输入

    现在前面的废话:最近好事不断!十分开心!生活真美好! 好了今天要梳理一下,顶点输入的具体过程,同样也是渲染管线中的第一个阶段的详细过程的介绍.之前介绍过,OpenGL操作的是一组3D坐标,所以我们的输 ...

  4. 非常详细的Django使用Token(转)

    基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookie+session的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机 ...

  5. 【redis】redis应用场景,缓存的各种问题

    如果你还不知道redis的基本命令与基本使用方法,请看 [redis]redis基础命令学习集合 缓存 redis还有另外一个重要的应用领域——缓存 引用来自网友的图解释缓存在架构中的位置 默认情况下 ...

  6. C# ModBus 读取数据

    简单介绍: 项目上需要与多家公司做接口对接.我们提供接口的有,其他公司提供的接口也有.所有的接口全部对接完了,遇到一个非常棘手的问题,需要获取甲方船厂设备上的状态,就给了一个文档,文档上写了IP.端口 ...

  7. 交叉编译QT 5.6.2 Shell脚本

    测试环境:  CPU: AT91SAM9X35      Linux: Atmel提供的linux-at91-linux4sam_5.3 (Linux-4.1.0) 转载请注明: 凌云物网智科嵌入式实 ...

  8. .net打杂工程师的面试感想和总结

    上个月26号辞职了,今天开始第一场面试,随便写写感想,后面还会继续分享一些感想 前言 这个时候找工作是不是找死? 开门见山吧,95年的,之前做过两份工作,第一家公司在做了2年2个月,在北京,也就是去年 ...

  9. TokuDB · 引擎特性 · HybridDB for MySQL高压缩引擎TokuDB 揭秘

    原文出处:阿里云RDS-数据库内核组 HybridDB for MySQL(原名petadata)是面向在线事务(OLTP)和在线分析(OLAP)混合场景的关系型数据库.HybridDB采用一份数据存 ...

  10. ionic3.x脚手架(基于个人项目自用)

    ionic3项目开发脚手架(基于个人练习项目) 一.    基于ionic3的生产环境搭建 1.    配置安卓SDK: 安装jdk  --->  安装AndroidSDK (1)      安 ...