Android进阶——多线程系列之Semaphore、CyclicBarrier、CountDownLatch
2016-12-21 17:57
441 查看
前言
今天向大家介绍的是多线程开发中的一些辅助类,他们的作用无非就是帮助我们让多个线程按照我们想要的执行顺序来执行。如果我们按照文字来理解Semaphore、CyclicBarrier、CountDownLatch可能会有点难度,如果看完实例再来看文字会恍然大悟。不用担心,今天带领大家用生活例子来理解这三个类,废话不多说,开车啦Semaphore
Semaphore是一个计数信号量。信号量中维护着一个信号量许可集,线程可以通过调用acquire()来获取信号量的许可。当信号量被许可时,线程可以向下执行,否则线程等待。同时,线程也可以通过release()来释放它的信号量。Semaphore简单的可以理解为一张许可证一、饭堂打饭
public class SemaphoreActivity extends AppCompatActivity { //线程数 private static final int THREAD_SIZE = 5; private Semaphore semaphore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_semaphore); semaphore = new Semaphore(3); for (int i = 0; i < THREAD_SIZE; i++) { new CanteenThread().start(); } } private class CanteenThread extends Thread { @Override public void run() { try { //买到粮票 semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "号买到粮票"); //模拟食堂打饭中 System.out.println(Thread.currentThread().getName() + "号窗口开始打饭"); Thread.sleep(2000); //提交粮票 semaphore.release(); System.out.println(Thread.currentThread().getName() + "号提交粮票"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
这里模拟了学生到食堂打饭的过程:买到粮票->打饭->提交粮票。其中semaphore代表食堂只有三张粮票的买卖,也可以理解为只有三个打饭窗口。THREAD_SIZE代表有五个学生线程同时打饭。下面通过打印信息来查看执行过程
Thread-636号买到粮票 Thread-636号窗口开始打饭 Thread-632号买到粮票 Thread-632号窗口开始打饭 Thread-635号买到粮票 Thread-635号窗口开始打饭 ......隔了2秒后 Thread-636号提交粮票 Thread-633号买到粮票 Thread-633号窗口开始打饭 Thread-632号提交粮票 Thread-634号买到粮票 Thread-634号窗口开始打饭 Thread-635号提交粮票 Thread-633号提交粮票 Thread-634号提交粮票
学生们打饭还是井然有序的,打完就撤,留给下一位。Semaphore就是一张通行证,灵活使用它,你就能指挥线程
二、打印机
public class PrinterActivity extends AppCompatActivity { //线程数 private static final int THREAD_SIZE = 5; private Semaphore semaphore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_printer); semaphore = new Semaphore(1); for (int i = 0; i < THREAD_SIZE; i++) { new PrinterThread().start(); } } private class PrinterThread extends Thread { @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "进入打印"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "打印中..."); System.out.println(Thread.currentThread().getName() + "退出打印"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
这里模拟五个人抢占一部打印机的场景。下面通过打印信息来查看执行过程
Thread-231进入打印 Thread-231打印中... Thread-231退出打印 Thread-229进入打印 Thread-229打印中... Thread-229退出打印 Thread-228进入打印 Thread-228打印中... Thread-228退出打印 Thread-230进入打印 Thread-230打印中... Thread-230退出打印 Thread-227进入打印 Thread-227打印中... Thread-227退出打印
CyclicBarrier
CyclicBarrier是一个同步辅助类,可以让正在运行中的线程与其他线程在某一公共时刻进行同步。CyclicBarrier简单理解为闸门,当我们达到某一目标时,闸门即可打开。一、短跑比赛
public class MatchActivity extends AppCompatActivity { //线程数 private static final int THREAD_SIZE = 5; private CyclicBarrier cb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_match); cb = new CyclicBarrier(THREAD_SIZE, new Runnable() { @Override public void run() { //裁判 System.out.println("参赛者" + cb.getParties() + "个全部准备完毕 --> 各就各位,预备跑"); } }); for (int i = 0; i < THREAD_SIZE; i++) { new AthleteThread().start(); } System.out.println("主线程不用等待,继续执行"); } private class AthleteThread extends Thread { @Override public void run() { try { //运动员 System.out.println(Thread.currentThread().getName() + "号选手准备好了"); cb.await(); System.out.println(Thread.currentThread().getName() + "跑,跑,跑"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }
这里模拟短跑比赛的过程:全部运动员准备->裁判一声令下->全部运动员开跑。其中THREAD_SIZE代表五名运动员,CyclicBarrier代表裁判。下面通过打印信息来查看这场比赛
Thread-682号选手准备好了 Thread-683号选手准备好了 Thread-684号选手准备好了 主线程不用等待,继续执行 Thread-686号选手准备好了 Thread-685号选手准备好了 参赛者5个全部准备完毕 --> 各就各位,预备跑 Thread-685跑,跑,跑 Thread-682跑,跑,跑 Thread-683跑,跑,跑 Thread-684跑,跑,跑 Thread-686跑,跑,跑
全部运动员们是在准备好之后开始起跑,这也就是我们所说的线程同步。它的特点是主线程不用等待,继续执行。
二、门禁系统
public class DoorActivity extends AppCompatActivity { //线程数 private static final int THREAD_SIZE = 10; private CyclicBarrier cb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_door); cb = new CyclicBarrier(THREAD_SIZE, new Runnable() { @Override public void run() { System.out.println("人到齐了 --> 开门"); } }); for (int i = 0; i < THREAD_SIZE; i++) { new PeopleThread().start(); } System.out.println("主线程不用等待,继续执行"); } private class PeopleThread extends Thread { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "已刷卡 --> 等待开门回家"); cb.await(); System.out.println(Thread.currentThread().getName() + "放学回家"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }
这里模拟十个学生放学回家的场景。下面通过打印信息来查看执行过程
Thread-268已刷卡 --> 等待开门回家 Thread-267已刷卡 --> 等待开门回家 主线程不用等待,继续执行 Thread-271已刷卡 --> 等待开门回家 Thread-272已刷卡 --> 等待开门回家 Thread-269已刷卡 --> 等待开门回家 Thread-270已刷卡 --> 等待开门回家 Thread-274已刷卡 --> 等待开门回家 Thread-273已刷卡 --> 等待开门回家 Thread-275已刷卡 --> 等待开门回家 Thread-276已刷卡 --> 等待开门回家 人到齐了 --> 开门 Thread-276放学回家 Thread-268放学回家 Thread-267放学回家 Thread-271放学回家 Thread-272放学回家 Thread-269放学回家 Thread-270放学回家 Thread-274放学回家 Thread-273放学回家 Thread-275放学回家
CountDownLatch
CountDownLatch也是一个同步辅助类,它可以设置一个或多个线程同时等待,直到条件被满足后,继续执行。一、面试
public class CountDownLatchActivity extends AppCompatActivity { //线程数 private static final int THREAD_SIZE = 5; private CountDownLatch cdl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_count_down_latch); try { cdl = new CountDownLatch(THREAD_SIZE); for (int i = 0; i < THREAD_SIZE; i++) { new IntervieweeThread().start(); } //开始面试 System.out.println("主线程需要等待"); cdl.await(); System.out.println("主线程继续执行 --> 面试会议结束了"); } catch (InterruptedException e) { e.printStackTrace(); } } private class IntervieweeThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "号面试者,开始面试"); cdl.countDown(); System.out.println(Thread.currentThread().getName() + "面试中...面试成功"); } } }
这里模拟面试的过程:面试者进来->面试完成->面试者进来->面试完成的循环过程。其中THREAD_SIZE代表五名面试者,CountDownLatch代表面试这场会议。下面通过打印信息来查看面试过程
Thread-757号面试者,开始面试 Thread-757面试中...面试成功 Thread-758号面试者,开始面试 Thread-758面试中...面试成功 Thread-759号面试者,开始面试 Thread-759面试中...面试成功 主线程需要等待 Thread-760号面试者,开始面试 Thread-760面试中...面试成功 Thread-761号面试者,开始面试 Thread-761面试中...面试成功 主线程继续执行 --> 面试会议结束了
面试者是一个一个执行的,它的特点是可以让主线程进入等待状态,直到我们规定的五名面试者完成后才继续执行。
二、家人团圆饭
public class FamilyActivity extends AppCompatActivity { private CountDownLatch cdl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_family); cdl = new CountDownLatch(3); new Thread() { public void run() { fatherToRes(); cdl.countDown(); } }.start(); new Thread() { public void run() { motherToRes(); cdl.countDown(); } }.start(); new Thread() { public void run() { meToRes(); cdl.countDown(); } }.start(); try { cdl.await(); togetherToEat(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void fatherToRes() { System.out.println("爸爸步行去饭店需要3小时。"); } public static void motherToRes() { System.out.println("妈妈挤公交去饭店需要2小时。"); } public static void meToRes() { System.out.println("我乘地铁去饭店需要1小时。"); } public static void togetherToEat() { System.out.println("一家人到齐了,开始吃饭"); } }
这里模拟一家三口回家吃团圆饭的场景,下面通过打印信息来查看执行过程
妈妈挤公交去饭店需要2小时。 爸爸步行去饭店需要3小时。 我乘地铁去饭店需要1小时。 一家人到齐了,开始吃饭
CyclicBarrier和CountDownLatch区别
CyclicBarrier和CountDownLatch看起来很相似,但还是有一些不同点:CountDownLatch的作用是允许1个或N个线程等待其他线程完成执行(刚才就是允许主线程等待),而CyclicBarrier则是允许N个线程相互等待。
CountDownLatch的计数器无法被重置,CyclicBarrier的计数器可以被重置后使用。
相关文章推荐
- 多线程系列之Semaphore、CyclicBarrier、CountDownLatch
- Java/Android多线程并发、同步,线程之间通信,主、子线程的一些问题(CountDownLatch、CyclicBarrier和Semaphore)
- java多线程并发(一)Semaphore,volatile,synchronized ,Lock, CyclicBarrier和CountDownLatch
- CountDownLatch,Semaphore,CyclicBarrier多线程工具类的使用
- 多线程系列十一-同步CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch,CyclicBarrier,Semaphore
- java多线程 栅栏(CyclicBarrier) 和 多线程辅助类 CountDownLatch
- CountDownLatch、CyclicBarrier和Semaphore
- 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
- java之JUC系列-外部Tools-Executors|Semaphor|Exchanger|CyclicBarrier|CountDownLatch
- Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析
- java多线程-concurrent-CountDownLatch和CyclicBarrier
- java多线程开发之CyclicBarrier,CountDownLatch
- Android进阶——多线程系列之四大线程池的使用介绍
- Java多线程——其他工具类CyclicBarrier、CountDownLatch和Exchange
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
- CountDownLatch,CyclicBarrier,Semaphore
- 多线程并发常用类:condition,semaphore,CyclicBarrier,countdownlatch,exchanger使用整理
- CountDownLatch、CyclicBarrier和Semaphore区别
- CountDownLatch、CyclicBarrier和Semaphore