1,AQS 同步的两种数据结构如下:
图
2.Semapheore 是什么?
emaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目。
2.1 构造方法:
2.3 基本使用:
2.3.1 需求场景
资源访问,服务限流
public class SemaphoreSample {public static void main(String[] args) { Semaphore semaphore = new Semaphore(2);for (int i=0;i<5;i++){new Thread(new Task(semaphore,"yangguo+"+i)).start(); } }static class Task extends Thread{ Semaphore semaphore;
public Task(Semaphore semaphore,String tname){this.semaphore = semaphore;this.setName(tname); }public void run() {try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+":aquire() attime:"+System.currentTimeMillis()); Thread.sleep(1000);semaphore.release();System.out.println(Thread.currentThread().getName()+":aquire() attime:"+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }}打印结果:Thread-3:aquire() at time:1563096128901Thread-1:aquire() at time:1563096128901Thread-1:aquire() at time:1563096129903Thread-7:aquire() at time:1563096129903Thread-5:aquire() at time:1563096129903Thread-3:aquire() at time:1563096129903Thread-7:aquire() at time:1563096130903Thread-5:aquire() at time:1563096130903Thread-9:aquire() at time:1563096130903Thread-9:aquire() at time:1563096131903从打印结果可以看出,一次只有两个线程执行 acquire(),只有线程进行 release() 方法后才会有别的线程执行 acquire()。
结果可以分析:
一次只有2个线程执行acquier(),只有线程relsase 额:
从打印结果可以看出,一次只有两个线程执行 acquire(),只有线程进行 release() 方法后
才会有别的线程执行 acquire()。
2.
CountDownLatch使用及应用场景
例子
CountDownLatch是什么?
CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例
如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执
行。
CountDownLatch如何工作?
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当
一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的
线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任
常见API:
demo:
CountDownLatch
.countDown()
CountDownLatch
场景:
/** * 看大夫任务 */public class SeeDoctorTask implements Runnable {private CountDownLatch countDownLatch;public SeeDoctorTask(CountDownLatch countDownLatch){this.countDownLatch = countDownLatch; }public void run() {
try { System.out.println("开始看医生"); Thread.sleep(3000); System.out.println("看医生结束,准备离开病房"); } catch (InterruptedException e) { e.printStackTrace(); }finally {if (countDownLatch != null)countDownLatch.countDown()
/** * 排队的任务 */public class QueueTask implements Runnable {private CountDownLatch countDownLatch;public QueueTask(CountDownLatch countDownLatch){this.countDownLatch = countDownLatch; }public void run() {try { System.out.println("开始在医院药房排队买药...."); Thread.sleep(5000); System.out.println("排队成功,可以开始缴费买药"); } catch (InterruptedException e) { e.printStackTrace(); }finally {if (countDownLatch != null)countDownLatch.countDown(); } }
public class CountDownLaunchSample {public static void main(String[] args) throwsInterruptedException {long now = System.currentTimeMillis(); CountDownLatch countDownLatch = new CountDownLatch(2);new Thread(new SeeDoctorTask(countDownLatch)).start();new Thread(new QueueTask(countDownLatch)).start();//等待线程池中的2个任务执行完毕,否则一直countDownLatch.await(); System.out.println("over,回家 cost:"+(System.currentTimeMillis()now)); }}
CyclicBarrier
Executors
主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单
重要方法
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需
要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的
线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执
行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作
线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
demo: