并发编程(二)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 ...
随机推荐
- 65. sqlserver执行存储过程实例
declare @param varchar(500)exec sp_PUB_GetFlowStatus @ret output,10011,88,1,12print @ret
- Java的Synchronized
原理,注意看输入输出,不了解原理是想不到会这样输出的. http://www.cnblogs.com/paddix/p/5367116.html 还有一个要注意的是一个对象一个monitor类
- javaScript日期
日历 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <html> <head> <t ...
- IE浏览器中的加载项怎么删除
IE浏览器中的加载项是一些软件或者浏览器的功能控件,我们可以通过禁用.开启来控制是否使用某些加载项,同时可以将一些加载项删除. 比如当我们遇到了一些不好的加载项,想要将它删除,通过这篇经验,教大家怎么 ...
- 遍历Datatable
//方法一 DataSet dataSet = new DataSet(); DataTable dt = dataSet.Tables[]; ; i < dt.Rows.Count; i++) ...
- vue深入了解组件——组件注册
一.组件名 在注册一个组件的时候,我们始终需要给它一个名字.比如在全局注册的时候我们已经看到了: Vue.component('my-component-name', { /* ... */ }) J ...
- session会话时间
session对象失效在下列情况下被删除: A.程序调用HttpSession.invalidate() B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间 ...
- scala --操作符和运算
基本类型和操作 scala 的基本类型包括如下几种 数类型 整数类型 :Byte Short Int Long 小数类型: Float Double 字符类型:Char 用'' 单引号包裹,是 ...
- cookie保存用户名及密码
登陆页中,用户输入用户名密码,点击提交,后台对照mysq数据库中,看是否有对应的用户名,以及密码是否正确.如果正确 则将用户名密码分两份Cookie保存.页面跳转到登陆成功页. 用户再次访问登陆页时, ...
- WEB性能测试工具
做Web开发,难免要对自己开发的页面进行性能检测,自己写工具检测,工作量太大.网上有几款比较成熟的检测工具,以下就介绍一下,与大家分享. 互联网现有工具 基于网页分析工具: 1. 阿里测 ...