并发编程(二)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 ...
随机推荐
- JS - 循环,条件if,switch,while
1.循环格式: 定义初始值 终止条件 // 1.将i的值写在里面 for(var i=0;i;i ++){ console.log(i); }// 2.也可以将i的值写在外面,分号必须还在 va ...
- html_table表格
## `table`表格 表格的常用标签 - `table`表格- `thead`表格头- `tbody`表格主体- `tfoot`表格尾- `th`元素定义表头单元格- `tr`定义表格行- `td ...
- @Repository的作用
一.@Repository 是用来注解接口的 如: @Repository("UserDao")public interface IUserDao {} 二,为什么有时候我们不用@ ...
- Java架构技术知识点梳理
Java程序员应该加以重视: 吃透基础技术 养成良好的阅读源码的习惯 有长期的技术学习规划 下面,我们来一起逐条看看,特别是第 3 个方法. 想要做到年薪50万,首先你自己必须是高水平的程序员! 能年 ...
- VB6单片机编程中的汉字处理
在DOS时代,拥有一个华丽的汉字菜单几乎是每个高档中文应用程序必须的包装.中文Windows操作系统的出现使得高级开发平台实现全中文的提示和界面非常容易和方便.在一般的应用程序中已经很少需要去专门考虑 ...
- padding 扩大边距 margin-top 与页面顶部的距离 hover鼠标移动到上面出现背景色CSS
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- UI5-文档-4.9-Component Configuration
在我们介绍了模型-视图-控制器(MVC)概念的所有三个部分之后,现在我们将讨论SAPUI5的另一个重要的结构方面. 在这一步中,我们将把所有UI资产封装在一个独立于索引的组件中.html文件.组件是S ...
- import tensorflow 报错,CentOS 升级 glibc
问题描述: ]: import tensorflow as tf ImportError: /lib64/libc.so.: version `GLIBC_2.' not found (require ...
- Cachefiled
NFS不同共享客户端间的数据不同步 问题现象 当您用台ECS挂载同一个NFS文件系统,在ECS-A上append写文件,在ECS-B用tail -f观察文件内容的变化.在ECS-A写完之后,在ECS- ...
- linux numastat的理解
numa的统计数据及理解如下, [root@localhost kernel]# numastat node0 node1numa_hit ...