1、J.U.C整理架构图
2、Tools
2.1、Executors
Executors是一个线程池工具类
包含以下几个静态方法
A.newSingleThreadExecutor
单个线程的线程池。
B.newCachedThreadPool
这是一个可缓存的线程池,如果没有线程池中没有线程则自动创建。
C.newFixedThreadPool
固定长度的线程池。
D.newWorkStealingPool
使用SynchronousQueue阻塞队列的线程池。
2.2、Exchager
这里只介绍单槽交换,此类主要用户两个线程用来交换对象,例如:一个工厂线程负责生产对象(生产比较耗费资源),一个线程负责消费,将生产的对象传给此线程消费。只能用来两个线程交换,不能指定线程。
public class GradleTest {
static final CountDownLatch countDownLatch = new CountDownLatch(4);
static ExecutorService executorService = Executors.newCachedThreadPool();
static final Exchanger<String> exchanger=new Exchanger<String>();
static final Runnable run1 = ()->{
try {
String result = exchanger.exchange(Thread.currentThread().getName());
System.out.println("this is "+Thread.currentThread().getName()+" receive data:"+result);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
static final Runnable run2 = ()->{
try {
String result = exchanger.exchange(Thread.currentThread().getName());
System.out.println("this is "+Thread.currentThread().getName()+" receive data:"+result);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
};
static final Runnable run3 = ()->{
try {
String result = exchanger.exchange(Thread.currentThread().getName());
System.out.println("this is "+Thread.currentThread().getName()+" receive data:"+result);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
};
static final Runnable run4 = ()->{
try {
String result = exchanger.exchange(Thread.currentThread().getName());
System.out.println("this is "+Thread.currentThread().getName()+" receive data:"+result);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
};
@Test
public void testExchanger(){
executorService.execute(run1);
executorService.execute(run2);
executorService.execute(run3);
executorService.execute(run3);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2.3、Semaphore
Semaphore经常用于限制获取某种资源的线程数量。
以使用工具为例:因为只有2个工具,所以当大家申请工具的时候,最多允许两个线程同时使用工具。
下面代码我们看到,同时有5个线程申请两个工具,所以我们必须限制线程申请。当2个线程已经申请到工具
semaphore.acquire()
其他线程处于等待状态,等待使用工具的线程释放工具
semaphore.release(1)
public class SemaphoreTest {
static final Semaphore semaphore = new Semaphore(2,true);
static final Tools[] toolsArray = new Tools[]{new Tools(1), new Tools(2)};
static ExecutorService executorService = Executors.newCachedThreadPool();
static final CountDownLatch countDownLatch = new CountDownLatch(5);
static final Runnable fix1 = () -> {
try {
System.out.println(Thread.currentThread().getName()+"开始申请工具....");
long start = System.currentTimeMillis();
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"等待时间为"+(System.currentTimeMillis()-start));
System.out.println(Thread.currentThread().getName()+"审批通过....");
Tools unUsedTools = getUnUsedTools();
System.out.println(Thread.currentThread().getName()+"开始使用工具"+unUsedTools.getNo()+"....");
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(2,5));
realseTools(unUsedTools);
System.out.println(Thread.currentThread().getName()+"归还工具....");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
};
static Tools getUnUsedTools(){
for (Tools tools : toolsArray){
if(!tools.isUsed()){
tools.setUsed(true);
return tools;
}
}
return null;
}
static void realseTools(Tools tools){
tools.setUsed(false);
semaphore.release(1);
}
@Test
public void testSemaphore() {
executorService.execute(fix1);
executorService.execute(fix1);
executorService.execute(fix1);
executorService.execute(fix1);
executorService.execute(fix1);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.4 CyclicBarrier
CyclicBarrier为线程设立屏障,当所有线程到达屏障时才继续往下执行操作。
public class CyclicBarrierTest {
static final Runnable together = () -> {
System.out.println("大家一起出发去机场!");
};
static final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, together);
static ExecutorService executorService = Executors.newCachedThreadPool();
static final CountDownLatch countDownLatch = new CountDownLatch(5);
static final Runnable run = ()->{
System.out.println(Thread.currentThread().getName()+"到集合地点集合");
try {
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"到达机场开始登机");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
@Test
public void testCyclicBarrier() {
executorService.execute(new Thread(run,"张三"));
executorService.execute(new Thread(run,"李四"));
executorService.execute(new Thread(run,"王五"));
executorService.execute(new Thread(run,"赵六"));
executorService.execute(new Thread(run,"唐七"));
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3、Locks
3.1、ReentrantLock重入锁
在JDK5.0以前ReentrantLock的性能优于synchronized,但是在JDK6.0以后的版本两者的性能相差无几。ReentrantLock提供了比synchronized能加灵活的操作方式。
public class ReentrantLockTest {
static final Lock lock = new ReentrantLock(false);
static ExecutorService executorService = Executors.newCachedThreadPool();
static final CountDownLatch countDownLatch = new CountDownLatch(5);
static final Runnable run = ()->{
try {
lock.lockInterruptibly();
System.out.println(Thread.currentThread().getName()+"获取锁");
TimeUnit.SECONDS.sleep(2);
lock.lockInterruptibly();
System.out.println(Thread.currentThread().getName()+"再次获取锁");
TimeUnit.SECONDS.sleep(2);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
lock.unlock();
System.out.println(Thread.currentThread().getName()+"释放锁");
}
};
@Test
public void testReentrantLock(){
executorService.execute(run);
executorService.execute(run);
executorService.execute(run);
executorService.execute(run);
executorService.execute(run);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.2、Condition
condition是在JDK5.0之后才出现,他是用来替代传统的synchronized加Object的wait()和notify()方法的。
public class ConditionTest {
//公平锁
static final Lock lock = new ReentrantLock(true);
static final Condition empty = lock.newCondition();
static final Condition full = lock.newCondition();
//生成容器
static LinkedList<Integer> container = new LinkedList<Integer>();
//已生成的数量
static volatile int hadProductNum = 0;
//已消费的数量
static volatile int hadConsumeNum = 0;
//容器最大数量
static final int maxContainerSize = 3;
//允许生成的最大数量
static final int maxNum = 20;
//工厂
static AtomicInteger factory = new AtomicInteger();
static class Producer implements Runnable {
@Override
public void run() {
for (; ; ) {
lock.lock();
try {
//容器满了则停止生产等待通知
if (container.size() == maxContainerSize) {
System.out.println(Thread.currentThread().getName() + "容器满了休眠");
full.await();
}
if (hadProductNum == maxNum) {
System.out.println(Thread.currentThread().getName() + "达到生成上限退出");
return;
}
int product = factory.incrementAndGet();
container.addLast(product);
System.out.println(Thread.currentThread().getName() + " 生成 " + product);
hadProductNum++;
empty.signal();
} catch (InterruptedException e) {
} finally {
lock.unlock();
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
for (; ; ) {
lock.lock();
try {
if (hadConsumeNum == maxNum) {
System.out.println(Thread.currentThread().getName() + "以消费所有退出");
return;
}
//容器没有数据则休息一会
if (container.isEmpty()) {
System.out.println(Thread.currentThread().getName() + "容器为空休眠");
empty.await(2, TimeUnit.SECONDS);
}
Integer product = container.removeFirst();
System.out.println(Thread.currentThread().getName() + " 消费" + product);
hadConsumeNum++;
full.signal();
} catch (InterruptedException e) {
} finally {
lock.unlock();
}
}
}
}
@Test
public void testCondition(){
Thread p1 = new Thread(new Producer(), "p-1");
Thread p2 = new Thread(new Producer(), "p-2");
Thread p3 = new Thread(new Producer(), "p-3");
Thread c1 = new Thread(new Consumer(), "c-1");
Thread c2 = new Thread(new Consumer(), "c-2");
Thread c3 = new Thread(new Consumer(), "c-3");
c1.start();
c2.start();
c3.start();
p1.start();
p2.start();
p3.start();
try{
c1.join();
c2.join();
c3.join();
p1.join();
p2.join();
p3.join();
}catch(Exception e){
}
System.out.println(" 完成. ");
}
}
4、ReadWriteLock
4.1、ReentrantReadWriteLock
ReentrantReadWriteLock是da有ReentrantLock语义的读写锁
(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。
(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.
(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。
(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。
(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常。
5、LockSupport
LockSupport提供park()和unpark()方法实现阻塞线程和解除线程阻塞,实现的阻塞和解除阻塞是基于”许可(permit)”作为关联,permit相当于一个信号量(0,1),默认是0. 线程之间不再需要一个Object或者其它变量来存储状态,不再需要关心对方的状态.