JUC的几个类
AtomicInteger确保原子性的原理
-
底层 使用unsafe 类实现
unsafe 直接操作的是地址值,cup的原语支持,确保了原子性。 -
unsafe运用的是CAS思想
compareAndSet(Object var1 , long valueOffset 地址值,int b 更新值)
{int var5; do{ //通过地址值获取最新的值 var5 = this.getIntVolatile(var1, valueOffset ) }while(!this.compareAndSwapInt(var1, valueOffset , var5, b)) //compareAndSwapInt中再次通过地址值获取当前值, 如果等于期望值var5就更新成b值,否则就重新获取期望值,继续自旋。
}
Lock接口-ReentrantLock类
1. 默认是非公平锁 :当线程进来时可以直接去获取锁资源,如果拿不到就去排队。
2. new ReentrantLock(true) 公平锁:所有线程需要排队等待
3. Lock lock = new ReentrantLock() lock.lock()获取锁
任务结束后一定要释放锁 lock.unLock();
4. 与synchronized 会在方法执行完或者程序终止时自动释放锁。
ReadWriteLock接口-ReentrantReadWriteLock类读写锁
1. ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
2. Lock readLock = lock.readLock(); 读锁也叫共享锁
3. Lock writeLock = lock.writeLock(); 写锁也叫排它锁
CountDownLatch 人走完了结束
1. CountDownLatch a = CountDownLatch(10);
2. for (int i=0; i< 10; i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+ "走了");
countDownLatch.countDown(); //每次调用值减一
}).start();
}
3. try {
countDownLatch.await();
System.out.println("人走完了结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
CyclicBarrier 人满开车
1.CyclicBarrier a = CyclicBarrier(20,new Runnable() {
@Override
public void run() {
System.out.println("人满开车");
})
2.for (int i=0; i< 20; i++){
new Thread(()->{
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
} // 只有当 等待的线程数到了20,才会执行人满开车
Semaphore 限流
1. Semaphore semaphore = new Semaphore(2); //同一时间最大两个线程执行
2. for (int i=0; i< 10; i++){
new Thread(()->{
try {
semaphore.acquire();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+ "在执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
3.结果:Thread-1在执行 Thread-0在执行
Exchanger exchanger = new Exchanger<>();
1. Exchanger<String> exchanger = new Exchanger<>();
2. new Thread(()->{
String s = "T1";
try {
s = exchanger.exchange(s); //等待另个线程就绪后交换s值
System.out.println(Thread.currentThread().getName()
+ "执行了交换T1变成了"+s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
3.new Thread(()->{
String s = "T2";
try {
s = exchanger.exchange(s); //等待另个线程就绪后交换s值
System.out.println(Thread.currentThread().getName()
+ "执行了交换T2变成了"+s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
4.结果:Thread-0执行了交换T1变成了T2 Thread-1执行了交换T2变成了T1
LockSupport 线程阻塞
1. Thread t1 = new Thread(()->{
2. LockSupport .park(); //阻塞t1线程
3. })
4. lock.unPark(t1); //唤醒t1线程