CountDownLauch
作用:是一组线程等待其他的线程完成工作以后在执行,加强版join
await用来等待,countDown负责计数器的减一
countDownLauch设定的次数必须减少到0,await的方法才会被唤醒向下继续执行,否则当一直处于阻塞状态
public class CountDownLatchDemo {
static CountDownLatch countDownLatch = new CountDownLatch(5);
private static class MyWork extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " do work");
countDownLatch.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("main wait other work done");
Thread.sleep(1000);
for (int i = 0; i < 5; i++) {
new MyWork().start();
}
countDownLatch.await();
System.out.println("main do work");
}
}
运行结果:
main wait other work done
Thread-0 do work
Thread-3 do work
Thread-1 do work
Thread-4 do work
Thread-2 do work
main do work
CyclicBarrier
CyclicBarrier(int parties) 让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行
CyclicBarrier(int parties, Runnable barrierAction),屏障开放,barrierAction定义的任务会执行
示例1:CyclicBarrier(int parties)
public class CyclicBarrierDemo {
static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
static class MyWork extends Thread {
@Override
public void run() {
Random r = new Random();
try {
if (r.nextBoolean()) {
System.out.println("Thread " + Thread.currentThread().getId() + " is sleeping");
Thread.sleep(2000);
}
System.out.println("Thread " + Thread.currentThread().getId() + " is await");
cyclicBarrier.await();//等待其他线程完毕
System.out.println("Thread " + Thread.currentThread().getId() + " is working");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new MyWork().start();
}
}
}
结果:
Thread 14 is await
Thread 13 is sleeping
Thread 12 is sleeping
Thread 11 is sleeping
Thread 15 is sleeping
Thread 13 is await
Thread 12 is await
Thread 11 is await
Thread 15 is await
Thread 15 is working
Thread 14 is working
Thread 12 is working
Thread 13 is working
Thread 11 is working
示例2:CyclicBarrier(int parties, Runnable barrierAction)
static CyclicBarrier cyclicBarrier = new CyclicBarrier(5,new OtherWork());
static class OtherWork implements Runnable{
@Override
public void run() {
System.out.println("Other work is doing");
}
}
结果:
Thread 15 is await
Thread 11 is sleeping
Thread 14 is sleeping
Thread 12 is sleeping
Thread 13 is await
Thread 14 is await
Thread 11 is await
Thread 12 is await
Other work is doing
Thread 15 is working
Thread 13 is working
Thread 14 is working
Thread 11 is working
Thread 12 is working
CountDownLauch & CyclicBarrier 的区别
1、countdownlatch放行由第三者控制,CyclicBarrier放行由一组线程本身控制
2、countdownlatch放行条件》=线程数,CyclicBarrier放行条件=线程数
Semaphore
控制同一时刻方法资源的数量
Semaphore(int permits) 表示同时获得资源数量
acquire() 从信号量容器中获取可用的信号量,信号量数量-1,如果没有可用信号量则阻塞
release()归还信号量到信号量容器中,信号量数量+1
示例:模拟获取数据库连接,规定同时只有10个可用数据库连接
public class SemaphoreDemo {
private final static int POOL_SIZE = 10;
static LinkedList<Connection> pool = new LinkedList<Connection>();
private Semaphore useable,unUseable;//useable表示可用的信号量,unUseable表示不可用
public SemaphoreDemo(){
useable = new Semaphore(10);
unUseable = new Semaphore(0);
}
static {
for (int i = 0; i < POOL_SIZE; i++) {
pool.add(MyConnection.getInstance());
}
}
public void releaseConnection(Connection connection) throws InterruptedException {
if(connection != null){
unUseable.acquire();
synchronized (pool){
pool.addLast(connection);
}
useable.release();
System.out.println("当前可用连接数为:"+useable.availablePermits()+",等待连接数:"+useable.getQueueLength());
}
}
public Connection getConnection() throws InterruptedException {
useable.acquire();
Connection connection = null;
synchronized (pool){
connection = pool.removeFirst();
}
unUseable.release();
return connection;
}
}
public class SemaphoreTest {
static SemaphoreDemo demo = new SemaphoreDemo();
static class ConnectionThread extends Thread {
@Override
public void run() {
long start = System.currentTimeMillis();
try {
Connection connection = demo.getConnection();
System.out.println("Thread_" + Thread.currentThread().getId()
+ "_获取数据库连接共耗时【" + (System.currentTimeMillis() - start) + "】ms.");
Thread.sleep(100);//模拟业务操作,线程持有连接查询数据
System.out.println("Thread_" + Thread.currentThread().getId()
+ "查询数据完成,归还连接!");
demo.releaseConnection(connection);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new ConnectionThread().start();
}
}
}
运行结果:
hread_11_获取数据库连接共耗时【0】ms.
Thread_14_获取数据库连接共耗时【0】ms.
Thread_13_获取数据库连接共耗时【0】ms.
Thread_12_获取数据库连接共耗时【0】ms.
Thread_16_获取数据库连接共耗时【0】ms.
Thread_17_获取数据库连接共耗时【0】ms.
Thread_18_获取数据库连接共耗时【0】ms.
Thread_20_获取数据库连接共耗时【0】ms.
Thread_15_获取数据库连接共耗时【0】ms.
Thread_21_获取数据库连接共耗时【0】ms.
Thread_11查询数据完成,归还连接!
Thread_19_获取数据库连接共耗时【97】ms.
当前可用连接数为:0,等待连接数:9
Thread_14查询数据完成,归还连接!
Thread_22_获取数据库连接共耗时【98】ms.
当前可用连接数为:0,等待连接数:8
Thread_18查询数据完成,归还连接!
Thread_23_获取数据库连接共耗时【98】ms.
当前可用连接数为:0,等待连接数:7
Thread_12查询数据完成,归还连接!
当前可用连接数为:1,等待连接数:7
Thread_15查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:7
Thread_16查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:6
Thread_24_获取数据库连接共耗时【99】ms.
Thread_20查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:5
Thread_25_获取数据库连接共耗时【100】ms.
Thread_13查询数据完成,归还连接!
当前可用连接数为:3,等待连接数:5
Thread_17查询数据完成,归还连接!
当前可用连接数为:4,等待连接数:5
Thread_21查询数据完成,归还连接!
当前可用连接数为:5,等待连接数:5
Thread_27_获取数据库连接共耗时【100】ms.
Thread_29_获取数据库连接共耗时【100】ms.
Thread_26_获取数据库连接共耗时【100】ms.
Thread_28_获取数据库连接共耗时【100】ms.
Thread_30_获取数据库连接共耗时【100】ms.
Thread_19查询数据完成,归还连接!
当前可用连接数为:1,等待连接数:0
Thread_22查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:0
Thread_23查询数据完成,归还连接!
当前可用连接数为:3,等待连接数:0
Thread_24查询数据完成,归还连接!
当前可用连接数为:4,等待连接数:0
Thread_25查询数据完成,归还连接!
当前可用连接数为:5,等待连接数:0
Thread_26查询数据完成,归还连接!
当前可用连接数为:6,等待连接数:0
Thread_30查询数据完成,归还连接!
当前可用连接数为:7,等待连接数:0
Thread_27查询数据完成,归还连接!
当前可用连接数为:8,等待连接数:0
Thread_28查询数据完成,归还连接!
当前可用连接数为:9,等待连接数:0
Thread_29查询数据完成,归还连接!
当前可用连接数为:10,等待连接数:0
Exchange
只能两个线程间的数据交换
示例:
public class ExchangeDemo {
static Exchanger<Set<String>> exchanger = new Exchanger<>();
static class MyThreadA extends Thread {
@Override
public void run() {
Set<String> setA = new HashSet<>();
setA.add("AAA");
setA.add("BBB");
setA.add("CCC");
try {
System.out.println("MyThreadA is waiting");
setA = exchanger.exchange(setA);
System.out.println("MyThreadA:" + setA);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class MyThreadB extends Thread {
@Override
public void run() {
Set<String> setB = new HashSet<>();
setB.add("DDD");
setB.add("EEE");
setB.add("FFF");
try {
Thread.sleep(1000);
System.out.println("MyThreadB is waiting");
setB = exchanger.exchange(setB);
System.out.println("MyThreadB:" + setB);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new MyThreadA().start();
new MyThreadB().start();
}
}
运行结果:
MyThreadA is waiting
MyThreadB is waiting
MyThreadB:[AAA, CCC, BBB]
MyThreadA:[EEE, DDD, FFF]
Callable, Future & FutureTask
三者之间的关系:
使用方式:new Thread(new FutureTask(new Callable()));
isDone,结束,正常还是异常结束,或者自己取消,返回true;
isCancelled 任务完成前被取消,返回true;
cancel(boolean):
- 任务还没开始,返回false
- 任务已经启动,cancel(true),中断正在运行的任务,中断成功,返回true,cancel(false),不会去中断已经运行的任务
- 任务已经结束,返回false
示例:
public class CallableDemo {
static class MyCallable implements Callable<Integer> {
int count;
@Override
public Integer call() throws Exception {
System.out.println("Call ready to sum");
Thread.sleep(2000);
for (int i = 0; i < 50; i++) {
count += i;
}
return count;
}
}
public static void main(String[] args) throws Exception {
Callable<Integer> callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
Random random = new Random();
if(random.nextBoolean()){
System.out.println("计算的结果为:"+futureTask.get());
}else{
futureTask.cancel(true);
System.out.println("task is cancle");
}
}
}
运行结果:
Call ready to sum
计算的结果为:1225