JUC并发编程--- 四个常用类
Posted 小样5411
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC并发编程--- 四个常用类相关的知识,希望对你有一定的参考价值。
前言
四个常用类
CountDownLatch—减法计数器
CyclicBarrier—参数达到就执行Runnable接口实现
Semaphore—并发限流
ReadWriteLock—读写锁
别急,现在分别用例子解释这四个类的用法
一、CountDownLatch
两个重要方法:countDown()和await()
这是一仿最后一个放学的同学关门案例,CountDownLatch作用就是用countDown()数量-1,await()等待计数器归零,然后向下执行,于是所有同学先走完,归零后,await()发现已经归零,于是向下执行Close Door
package com.yx.oftenClass;
import java.util.concurrent.CountDownLatch;
//减法计数器
public class countDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"->Go Out");
countDownLatch.countDown();//数量-1,这是它第一个重点方法
},String.valueOf(i)).start();
}
countDownLatch.await();//等待计数器归零,然后向下执行
System.out.println("Close Door");
}
}
效果
等所有结束后,执行await()下面的代码
二、CyclicBarrier
CyclicBarrier构造函数有两个参数
一个是表示数量到达parties,就执行线程实现,这里可以以集齐7张不同卡片兑换礼品案例
package com.yx.oftenClass;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
/**
* 集齐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();//等待是否满7个
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
三、Semaphore
Semaphore并发限流作用,比如抢车位,设置只有3个车位,那么必须要有车位才能抢,没有就只能等释放。
package com.yx.oftenClass;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class semaphoreDemo {
public static void main(String[] args) {
//线程数量,停车,并发限流
Semaphore semaphore = new Semaphore(3);//限制3个线程,相当于三个车位
for (int i = 0; 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 (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//释放
}
},String.valueOf(i)).start();
}
}
}
四、ReadWriteLock读写锁
读写锁就是在写的过程中只能有一个线程占用,读可以由多个线程读
package com.yx.oftenClass;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 独占锁(写锁):一次只能被一个线程占有
* 共享锁(读锁):多个线程可以同时占有
* 没有加锁的自定义写入是乱的,不能保证写入是只有一个线程
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
MyCacheLock myCacheLock = new MyCacheLock();
//写入
for (int i = 0; i < 5; i++) {
final int temp=i;
new Thread(()->{
myCacheLock.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
//读取
for (int i = 0; i < 5; i++) {
final int temp=i;
new Thread(()->{
myCacheLock.get(temp+"");
},String.valueOf(i)).start();
}
}
}
/**
* 自定义缓存
*/
class MyCache{
private volatile Map<String,Object> map = new HashMap<>();
//存,写
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入OK");
}
//取,读
public void get(String key){
System.out.println(Thread.currentThread().getName()+"读取"+key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()+"读取OK");
}
}
//加锁
class MyCacheLock{
private volatile Map<String,Object> map = new HashMap<>();
//读写锁,更加细粒度控制
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//存,写,独占
public void put(String key,Object value){
readWriteLock.writeLock().lock();
try {
//业务
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
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();
}
}
}
一开始用自己自定义的锁,然后用ReadWriteLock读写锁,对比可以看出写入操作就一个线程执行,执行完下一个才执行
以上是关于JUC并发编程--- 四个常用类的主要内容,如果未能解决你的问题,请参考以下文章