并发小工具,谁用谁知道(一)

Semaphore && CountDownLatch

Semaphore 

1. Semaphore 是什么?
Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目。
2. 怎么使用 Semaphore?
2.1 构造方法
public Semaphore(int permits)
public Semaphore(int permits, boolean fair)
permits 表示许可线程的数量
fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最久的线程
2.2 重要方法
public void acquire() throws InterruptedException
public void release()
tryAcquire(long timeout, TimeUnit unit)
acquire() 表示阻塞并获取许可 
release() 表示释放许可
2.3 基本使用
2.3.1 需求场景
资源访问,服务限流。
2.3.2 代码实现
 1 public class SemaphoreSample {
 2     public static void main(String[] args) {
 3         Semaphore semaphore = new Semaphore(2 4         for (int i=0;i<5;i++){
 5             new Thread(new Task(semaphore,"zhangjiang+"+i)).start();
 6         }
 7     }
 8 
 9     static class Task extends Thread{
10         Semaphore semaphore;
11         public Task(Semaphore semaphore,String tname){
12             this.semaphore = semaphore;
13             this.setName(tname);
14         }
15 
16         public void run() {
17             try{
18                 semaphore.acquire();
19            System.out.println(Thread.currentThread().getName()+":aquire() at time:"+System.currentTimeMillis());
20                 Thread.sleep(100021                 semaphore.release();
22                 System.out.println(Thread.currentThread().getName()+":aquire() at time:"+System.currentTimeMillis());
23             } catch (InterruptedException e) {
24                 e.printStackTrace();
25             }
26         }
27     }
28 }
View Code

打印结果:

Thread-3:aquire() at time:1563096128901 
Thread-1:aquire() at time:1563096128901 
Thread-1:aquire() at time:1563096129903 
Thread-7:aquire() at time:1563096129903 
Thread-5:aquire() at time:1563096129903 
Thread-3:aquire() at time:1563096129903 
Thread-7:aquire() at time:1563096130903 
Thread-5:aquire() at time:1563096130903 
Thread-9:aquire() at time:1563096130903 
Thread-9:aquire() at time:1563096131903
从打印结果可以看出,一次只有两个线程执行 acquire(),只有线程进行 release() 方法后才会有别的线程执行 acquire()。

CountDownLatch使用及应用场景例子

CountDownLatch是什么?
CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
CountDownLatch如何工作?
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
API
CountDownLatch.countDown() 
CountDownLatch.await();
CountDownLatch应用场景例子
比如陪好基友去看病。
医院里边排队的人很多,如果一个人的话,要先看大夫,看完大夫再去排队交钱取药。
现在我们是双核,可以同时做这两个事(多线程)。
假设看大夫花3秒钟,排队交费取药花5秒钟。我们同时搞的话,5秒钟我们就能完成,然后一起回家(回到主线程)。
代码如下:
看大夫任务
 1 /*** 看大夫任务 */ 
 2 public class SeeDoctorTask implements Runnable { 
 3     private CountDownLatch countDownLatch; 
 4 
 5     public SeeDoctorTask(CountDownLatch countDownLatch){                 
 6         this.countDownLatch = countDownLatch; 
 7     }
 8 
 9     public void run() {
10         try {
11             System.out.println("开始看医生"12             Thread.sleep(300013             System.out.println("看医生结束,准备离开病房"14         } catch (InterruptedException e) { 
15             e.printStackTrace(); 
16         }finally { 
17             if (countDownLatch != null)     
18                  countDownLatch.countDown();         
19         } 
20     } 
21 }    
View Code
排队的任务
 1 /*** 排队的任务 */ 
 2 public class QueueTask implements Runnable { 
 3     private CountDownLatch countDownLatch; 
 4 
 5     public QueueTask(CountDownLatch countDownLatch){     
 6         this.countDownLatch = countDownLatch; 
 7     }
 8 
 9     public void run() { 
10         try {
11             System.out.println("开始在医院药房排队买药...."12             Thread.sleep(500013             System.out.println("排队成功,可以开始缴费买药"14         } catch (InterruptedException e) { 
15             e.printStackTrace(); 
16         }finally { 
17             if (countDownLatch != null) 
18                  countDownLatch.countDown(); 
19         } 
20     }
21 }    
View Code
去排队准备交钱
 1 /***陪好基友去看病,轮到好基友看大夫时 * 我就开始去排队准备交钱了。 */ 
 2 public class CountDownLaunchSample { 
 3     public static void main(String[] args) throws InterruptedException { 
 4     long now = System.currentTimeMillis(); 
 5     CountDownLatch countDownLatch = new CountDownLatch(2 6     new Thread(new SeeDoctorTask(countDownLatch)).start(); 
 7     new Thread(new QueueTask(countDownLatch)).start(); 
 8     //等待线程池中的2个任务执行完毕,否则一直     
 9     countDownLatch.await(); 
10     System.out.println("over,回家 cost:"+ (System.currentTimeMillis()­now)); 
11     } 
12 }
View Code

 

posted @ 2020-10-20 22:44  powerZhangFly  阅读(88)  评论(0)    收藏  举报