并发编程(二)concurrent 工具类
并发编程(二)concurrent 工具类
一、CountDownLatch
经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest extends Thread {
private final static CountDownLatch countDown = new CountDownLatch(2); // (1)
@Override
public void run() {
// 唤醒线程线程
countDown.countDown(); // (2)
System.out.println(Thread.currentThread().getName() + "执行完毕...");
}
public static void main(String[] args) {
new Thread(new CountDownLatchTest()).start();
new Thread(new CountDownLatchTest()).start();
try {
Thread.sleep(1000);
countDown.await(); // (3)
System.out.println(Thread.currentThread().getName() + "继续执行...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
声明一个 CountDownLatch 对象,参数 2 表示被阻塞的线程需要被唤醒再次才能执行。
final CountDownLatch countDown = new CountDownLatch(2);
countDown() 调用两次后,主线程才会继续执行
countDown.countDown();
阻塞当前线程-main
countDown.await();
执行结果如下:
Thread-1执行完毕...
Thread-0执行完毕...
main继续执行... // Thread-0, Thread-1 执行完成才会继续执行主线程
二、CyclicBarrier
假设有只有的一个场景:每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个没有准备了,大家都等待。
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UseCyclicBarrier {
static class Runner implements Runnable {
private CyclicBarrier barrier;
private String name;
public Runner(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(1000 * (new Random()).nextInt(5));
System.out.println(name + " 准备OK.");
barrier.await(); //(1)
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(name + " Go!!");
}
}
public static void main(String[] args) throws IOException, InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(2); // (2)
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new Thread(new Runner(barrier, "Thread-1")));
executor.submit(new Thread(new Runner(barrier, "Thread-2")));
executor.shutdown();
}
}
await() 阻塞当前的线程。
barrier.await();
声明一个 CyclicBarrier 对象,参数 2 表示 barrier 必须有两个线程都准备好了才能执行。
CyclicBarrier barrier = new CyclicBarrier(2);
执行结果如下:
Thread-1 准备OK.
Thread-2 准备OK.
Thread-1 Go!!
Thread-2 Go!!
修改
CyclicBarrier barrier = new CyclicBarrier(3)后这两个线程都会被阻塞, 执行结果如下:Thread-1 准备OK.
Thread-2 准备OK.
三、Future
四、Semaphore
Semaphore 信号量非常适合高并发访问。
public class UseSemaphore {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5); // (1)
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire(); // (2)
System.out.println("Accessing: " + NO);
//模拟实际业务逻辑
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release(); // (3)
} catch (InterruptedException e) {
;
}
}
};
exec.execute(run);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(semp.getQueueLength());
// 退出线程池
exec.shutdown();
}
}
声明一个 Semaphore 对象,参数 5 表示最多有5个线程同时访问。
final Semaphore semp = new Semaphore(5);
semp.acquire()获取 semp 对象,如果超过5个线程,那么其余的线程就会阻塞,直到有线程执行完毕。semp.release()释放 semp 对象,这样其余的线程就可以执行了。
补充:
PV(page view) 网站的总访问量,页面浏览量或点击量,用户每刷新一次就会记录一次。
UV(unique vistor) 访问网站的一台电脑客户端为一个访客。一般来讲,时间上以00:00~24:00之内相同的客户端记录一次。
QPS(query per second) 即每秒查询数,QPS 很大程度代表了系统业务的繁忙程度。一旦当前 QPS 超过所设定的预警阀值,可以考虑对集群扩容,以免压力过大导致宕机。
RT(response time) 即请求的响应时间,这个指标非常关键,直接说明客户端的体验,因此任何系统设计师都想降低 RT 时间。
对系统进行峰值评估,采用所谓的80/20原则,即80%的请求20%的时间到达:
QRS = (PV * 80%) / (24 * 60 * 60 * 20%)
五、ReentrantLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockTest implements Runnable {
private Lock lock = new ReentrantLock(); // (1)
public void run(){
try {
lock.lock(); // (2)
System.out.println(Thread.currentThread().getName() + "进入..");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "退出..");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // (3)
}
}
public static void main(String[] args) throws InterruptedException {
final ReentrantLockTest ur = new ReentrantLockTest();
for (int i = 0; i < 10; i++) {
new Thread(ur).start();
}
}
}
ReentrantLock 一般用法:
private Lock lock = new ReentrantLock();
try {
lock.lock();
//do something
} finally {
lock.unlock();
}condition 使用方法,注意 condition 可以实例化多个:
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
condition.await(); //阻塞线程,释放锁
condition.signal();//唤醒线程,不释放锁
公平锁(true)和非公平锁(false),非公平锁执行效率比公平锁高
Lock lock = new ReentrantLock(boolean isFair);
读写锁,实现读写分离的锁,适用于读多写少的情况下(读读共享,读写互斥)
private ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(); // (1)
private ReadLock readLock = rwlock.readLock(); // (2)
private WriteLock writeLock = rwlock.writeLock(); // (3) public void read(){
try {
readLock.lock();
// do something
} finally {
readLock.unlock();
}
} public void write(){
try {
writeLock.lock();
// do something
} finally {
writeLock.unlock();
}
}
每天用心记录一点点。内容也许不重要,但习惯很重要!
并发编程(二)concurrent 工具类的更多相关文章
- 线程高级应用-心得6-java5线程并发库中同步工具类(synchronizers),新知识大用途
1.新知识普及 2. Semaphore工具类的使用案例 package com.java5.thread.newSkill; import java.util.concurrent.Executor ...
- Java并发编程二三事
Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...
- Java并发编程:Concurrent锁机制解析
Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ...
- 并发编程(Concurrent programming)
并发编程(Concurrent programming) 1.并发编程概述 2.委托(delegate) 3.事件(event) 4.线程(thread) 5.线程池(threadPool) 6.任务 ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- java并发编程:线程安全管理类--原子操作类--AtomicInteger
在java并发编程中,会出现++,--等操作,但是这些不是原子性操作,这在线程安全上面就会出现相应的问题.因此java提供了相应类的原子性操作类. 1.AtomicInteger
- 并发编程的基石——AQS类
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文参考了[Java多线程进阶(六)-- J.U.C之l ...
- 【Java并发编程二】同步容器和并发容器
一.同步容器 在Java中,同步容器包括两个部分,一个是vector和HashTable,查看vector.HashTable的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并 ...
- Java并发编程笔记之Unsafe类和LockSupport类源码分析
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...
随机推荐
- django框架预备知识
内容: 1.web预备知识 2.django介绍 3.web框架的本质及分类 4.django安装与基本设置 1.web预备知识 HTTP协议:https://www.cnblogs.com/wyb6 ...
- PHP图片压缩
<?php /** * 分享请保持网址.尊重别人劳动成果.谢谢. * 图片压缩类:通过缩放来压缩.如果要保持源图比例,把参数$percent保持为1即可. * 即使原比例压缩,也可大幅度缩小.数 ...
- 2018-2019-2 《网络对抗技术》Exp3 免杀原理与实践 Week5 20165233
Exp3 免杀原理与实践 实验内容 一.基础问题回答 1.杀软是如何检测出恶意代码的? 基于特征码的检测:通过与自己软件中病毒的特征库比对来检测的. 启发式的软件检测:就是根据些片面特征去推断.通常是 ...
- 网络命令ping/netstat/ipconfig/arp/tracert/nbstat
1.1 Ping命令的使用 ping检测网络故障步骤: ping 127.0.0.1 ping环绕指针检测是否在计算上anzhaung了TCP/IP协议及配置是否正确 ping本机IP这个命令被被送到 ...
- as3 air 获取文件夹下的所有文件
private function getFile(directory:File) { var files:Array = directory.getDirectoryListing(); for(va ...
- .NET MVC 两种视图引擎(Razor、Aspx)
ASPX 优点: 通过上面小小的对比,不难看出,与ASP.NET MVC紧密集成,对于以往ASP.NET开发人员有更好体验.其实它还有其他几优点: ●智能感应 ...
- Oracle SQL Developer在进行查询的时候只显示50条数据
在查询结果大于50条的时候,软件默认会只显示50条,向下拉会继续显示. 想要显示所有结果的话,光标放在结果集:ctrl+End或者是ctrl+PgDn都可以.
- js中对话框的使用
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- hadoop无法启动常见原因
1.Could not chdir to home directory /home/USER: Permission denied 启动datanode时会报这个错误,尝试利用ssh登录datanod ...
- Ansible playbooks
Playbook是Ansible的配置,部署和编排语言. 他们可以描述您希望远程系统执行的策略,或一般IT流程中的一组步骤. 如果Ansible modules是您workshop的工具,则playb ...