并发包ConcurrentHashMap CountDownLatch CyclicBarrier Semaphore Exchanger
并发包
ConcurrentHashMap
HashMap是线程不安全的,性能好
Hashtable是线程安全的Map集合,性能较差,已淘汰,整个数组全锁
ConcurrentHashMap线程安全,性能好,只锁自己操作的元素位置
public static Map<String, String> maps = new ConcurrentHashMap<>();
public static void main() {
Runnable target = new MyRunnable();
Thread t1 = new Thread(target, "线程1");
Thread t2 = new Thread(target, "线程2");
t1.start();
t2.start();
t1.join(); // t1执行完
t2.join(); // t2执行完
// HashMap得到的size不到1000000
System.out.println(maps.size());
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 500000; i++) {
Demo.maps.put(Thread.currentThread().getName() + i,
Thread.currentThread().getName());
}
}
}
CountDownLatch
需求:
A线程,打印A、C
B线程,打印B
当A线程先执行时,打印 A、B、C
public class CountDownLatchDemo {
public static void main() {
// 监督者 等待1步
CountDownLatch c = new CountDownLatch(1);
new ThreadA(c).start();
new ThreadB(c).start();
}
}
class ThreadA extends Thread {
private CountDownLatch c;
public ThreadA(CountDownLatch c) {
this.c = c;
}
@Override
public void run() {
System.out.println("A");
// 开始等待
c.await();
System.out.println("C");
}
}
class ThreadB extends Thread {
private CountDownLatch c;
public ThreadB(CountDownLatch c) {
this.c = c;
}
@Override
public void run() {
System.out.println("B");
// 计数器减1
c.countDown();
}
}
CyclicBarrier
多线程计算数据,最后合并计算结果
循环屏障
某个线程等待其他线程执行完毕才执行
五个员工都到齐,才执行开会的操作
class EmployeeThread extends Thread {
private CyclicBarrier c;
public EmployeeThread(String name, CyclicBarrier c) {
super(name);
this.c = c;
}
@Override
public void run() {
// 模拟员工正在进入会议室
Thread.sleep(3000);
// 告诉屏障自己已到达:障碍解除(被回收)
c.await();
}
}
class Meeting implements Runnable {
@Override
public void run() {
System.out.println("开会!");
}
}
public class MainDemo {
public static void main() {
// 5个员工开一次会
// 创建一个循环屏障,等5个线程执行完毕,触发一次开会任务
CyclicBarrier c = new CyclicBarrier(5, new Meeting());
for (int i = 0; i < 5; i++) {
new EmployeeThread("员工" + i, c).start();
}
}
}
Semaphore
控制线程并发的数量(1000万)
锁可以同时进三个线程
class Servie {
// 相当于是锁,用于控制流量,但会有安全问题
// 同时存在3个线程时,一个刚走,另一个就会进来,始终保持3个线程
private Semaphore semaphore = new Semaphore(1);
public void login() {
// 上锁
semaphore.acquire();
System.out.println("登录");
// 解锁
semaphore.release();
}
}
class MyThread extends Thread {
private Service service;
public MyThread(Service service) {
this.service = service;
}
@Override
public void run() {
service.login();
}
}
public class Test {
public static void main() {
Service service = new Service();
for(int i = 0; i < 5; i++) {
Thread a = new MyThread(service);
a.start();
}
}
}
Exchanger
可以做数据校对工作(两个人录同一份数据)
线程间的数据交换,不是等待和唤醒(没有交流数据)
同步交换数据,媒婆
public class Test {
public static void main() {
Exchanger<String> exchanger = new Exchanger();
new Thread(new Boy(exchanger));
new Thread(new Girl(exchanger));
}
}
class Boy extends Thread {
private Exchanger<String> exchanger;
public Boy(Exchanger exchanger) {
this.exchager = exchanger;
}
@Override
public void run() {
System.out.println("boy准备好的数据");
// 收到girl的数据(没收到会在这里等待)
// 可设置等待girl的时间,等不到就抛异常TimeoutException延时异常
String girlData = exchanger.exchange();
}
}
class Girl extends Thread {
private Exchanger<String> exchanger;
public Girl(Exchanger exchanger) {
this.exchager = exchanger;
}
@Override
public void run() {
System.out.println("girl准备好的数据");
// 收到boy的数据(没收到会在这里等待)
String boyData = exchanger.exchange();
}
}