CountDownLatch
减法计数器: 实现调用几次线程后 再触发某一个任务
//减法计数器
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
countDownLatch.countDown();// 数量-1
System.out.println(Thread.currentThread().getName()+" -1");
}, String.valueOf(i)).start();
}
countDownLatch.await();//等待计数器归零,往下执行
System.out.println("计数器归零啦!!!");
原理
- countDownLatch.countDown(); // 数量-1
- countDownLatch.await(); //等待计数器归零,然后再向下执行
- 每次有线程调用 countDown() 数量-1,假设计数器变为0,countDownLatch.await() 就会被唤醒,继续执行!
CyclicBarrier
sīklik berēər
加法计数器:集齐7颗龙珠召唤神龙
//减法计数器
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("召唤神龙成功!");
});
for (int i = 1; i <= 7; i++) {
final int temp=i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"收集第"+temp+"颗龙珠");
try {
cyclicBarrier.await();// 等待
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
Semaphore
// 线程数量:停车位! 限流!、
// 如果已有3个线程执行(3个车位已满),则其他线程需要等待‘车位’释放后,才能执行!
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
try {
semaphore.acquire(); // 得到
System.out.println(Thread.currentThread().getName()+"抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (Exception e) {
System.out.println(e);
}finally {
semaphore.release(); // 释放
}
},String.valueOf(i)).start();
}
原理
semaphore.acquire(); 获得,假设如果已经满了,等待,等待被释放为止!semaphore.release(); 释放,会将当前的信号量释放 + 1,然后唤醒等待的线程!
作用:
多个共享资源互斥的使用!并发限流,控制最大的线程数!
ReadWriteLock
public class ReadWriteLockDemo {
public static void main (String[] args) throws Exception {
/**
* * 独占锁(写锁) 一次只能被一个线程占有
* * 共享锁(读锁) 多个线程可以同时占有
* * ReadWriteLock
* * 读-读 可以共存!
* * 读-写 不能共存!
* * 写-写 不能共存!
*/
MyCacheLock myCacheLock = new MyCacheLock();
// 写入
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
// 读取
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.get(temp+"");
},String.valueOf(i)).start();
}
}
}
class MyCacheLock {
private Map<String, String> map = new HashMap<>();
// 读写锁: 更加细粒度的控制
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// private Lock lock = new ReentrantLock();
// 存,写入的时候,只希望同时只有一个线程写
public void put (String key, String val) {
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "写入" + key);
map.put(key, val);
System.out.println(Thread.currentThread().getName() + "写入OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
// 取,读,所有人都可以读!
public void get (String key) {
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "读取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
狂神JUC笔记:https://www.kuangstudy.com/bbs/1374937897278402561