多线程控制、同步的几个实用的类
2016-06-24 21:35
302 查看
多个线程之间的控制,最基本的就是相互之间的wait(),notify()等。其实java.util.concurrent类中已经有了好多同步辅助类,需要的时候感觉还是很好用的。用法整理一下,走起!
new Semaphore(int)。创建了一个自助提款站点,参数代表此站点有几个ATM机。
一个线程来了,调用semaphore.acquire(),占了一个ATM机。又来一个线程来占用ATM... 直到所有ATM都被占用后,再来线程调用semaphore.acquire(),那么这个线程就必须等待。直到其中有一个线程使用完毕,调用semaphore.release(),前面等待的线程才会停止等待,继续执行下去。
测试代码:
new CountDownLatch(int)。创建一个旅游活动,参数表示这个活动最少需要多少成员,活动才能顺利进行下去。
某个线程报到(调用countDownLatch.countDown()方法)。当没有达到最低数量要求,一些调用了countDownLatch.await()方法的线程会在此方法等待,直到报到的数量达到最低要求。
下面注释的带参数的几个方法意思是:设置等待时间,不管有没达到数量要求,到时间就不再等待。当然,如果没有达到要求会返回false,反之返回true。
new CyclicBarrier(4):这个意思是,对所有await的调用线程都会等待,直到await的次数达到指定值,此时,所有await的线程立即被唤醒。
其中带参数的await方法,是等待超时时间,如果等待超时,直接抛出TimeOutException。
举个栗子:一个任务有3个线程去并发执行,这个任务可以分为4个阶段,并且每个阶段结束,才能进行下个阶段。
那么new Phaser(3),就是三个线程并发执行。三个线程执行调用arriveAndAwaitAdvance()方法,这个方法会等待,直到执行arriveAndAwaitAdvance()方法到达3个后(意思就是当前阶段全部结束,可以进行下个阶段了),都被唤醒,继续执行。
1.Semaphore:
就叫它信号量吧。举个栗子就知道它是干啥的了。new Semaphore(int)。创建了一个自助提款站点,参数代表此站点有几个ATM机。
一个线程来了,调用semaphore.acquire(),占了一个ATM机。又来一个线程来占用ATM... 直到所有ATM都被占用后,再来线程调用semaphore.acquire(),那么这个线程就必须等待。直到其中有一个线程使用完毕,调用semaphore.release(),前面等待的线程才会停止等待,继续执行下去。
测试代码:
private void initSemaphore() throws InterruptedException { //这里只分配两个信号量,下面三个线程总会有一个抢不到,只能等待其他线程释放掉其信号。 mSemaphore = new Semaphore(2); for (int i = 0; i < 3; i++) { final String threadName = i + ""; new Thread() { @Override public void run() { super.run(); long l = System.currentTimeMillis(); try { <span style="color:#ff0000;">mSemaphore.acquire();</span> } catch (InterruptedException e) { e.printStackTrace(); } SystemClock.sleep(2000); Log.e(TAG, "Thread num is " + threadName + " is run!" + "Wait time:" + (System.currentTimeMillis() - l)); <span style="color:#ff0000;">mSemaphore.release();</span> } }.start(); } Log.e(TAG, "Threads run over"); }执行结果:
E/TAG: Threads run over E/TAG: Thread num is 2 is run!Wait time:2000 E/TAG: Thread num is 0 is run!Wait time:2001 E/TAG: Thread num is 1 is run!Wait time:3999可以看到,Thread num 为1 的线程运行时间成了4秒,因为它第一次没有抢到信号量,所以要等待其余两个线程释放信号量,它才会继续执行。
2.CountDownLatch
这个和上面那个有点相类似,还是来个栗子:new CountDownLatch(int)。创建一个旅游活动,参数表示这个活动最少需要多少成员,活动才能顺利进行下去。
某个线程报到(调用countDownLatch.countDown()方法)。当没有达到最低数量要求,一些调用了countDownLatch.await()方法的线程会在此方法等待,直到报到的数量达到最低要求。
测试代码:
private void initCountDownLatch() throws InterruptedException { mCountDownLatch = new CountDownLatch(3); long l = System.currentTimeMillis(); for (int i = 0; i < 3; i++) { final String threadName = i + ""; new Thread() { @Override public void run() { super.run(); SystemClock.sleep(2000); Log.e(TAG, "Thread num is " + threadName + " is run!"); <span style="color:#ff0000;">mCountDownLatch.countDown();</span> } }.start(); } <span style="color:#ff0000;">mCountDownLatch.await()</span>; Log.e(TAG, "Threads run over "+(System.currentTimeMillis()-l)); /*下面的方法 1.当到指定时间后,上面线程没有全部执行完,不再等待。return false; 2.当到指定时间前,上面线程全部执行完了,则不再等待。return true; 3.当被打断,抛异常。 */ // boolean result = mCountDownLatch.await(1000, TimeUnit.MILLISECONDS); //boolean result = mCountDownLatch.await(4000, TimeUnit.MILLISECONDS); //Log.e(TAG, "Threads run over result is " + result + " time is " + (System.currentTimeMillis() - l)); }
执行结果:
E/TAG: Thread num is 0 is run! E/TAG: Thread num is 2 is run! E/TAG: Thread num is 1 is run! E/TAG: Threads run over 2021可以看到,主线程会等待countDown()调用够3次后,await()方法才往下执行。
下面注释的带参数的几个方法意思是:设置等待时间,不管有没达到数量要求,到时间就不再等待。当然,如果没有达到要求会返回false,反之返回true。
下面是参数为4000ms的执行结果:
E/TAG: Thread num is 2 is run! E/TAG: Thread num is 1 is run! E/TAG: Thread num is 0 is run! E/TAG: Threads run over result is true time is 2017可以看到,当在设置时间前完成,这个参数是没有什么意义的,返回为true。
下面是参数为1000ms的执行结果:
E/TAG: Threads run over result is false time is 1004 E/TAG: Thread num is 0 is run! E/TAG: Thread num is 2 is run! E/TAG: Thread num is 1 is run!可以看到,当在设置时间前没有完成,不再等待,返回为false
3.CyclicBarrier
这个和上面的countDownLatch相似,上面是让某一个线程等待多个线程。这个是多个线程互相等待某一件事发送,才继续下去。new CyclicBarrier(4):这个意思是,对所有await的调用线程都会等待,直到await的次数达到指定值,此时,所有await的线程立即被唤醒。
测试代码:
private void initCyclicBarrier() { mCyclicBarrier = new CyclicBarrier(4); for (int i = 0; i < 3; i++) { final String threadName = i + ""; new Thread() { @Override public void run() { super.run(); Log.e(TAG, "Thread num is " + threadName + " is wait!"); try { <span style="color:#ff0000;"> int result = mCyclicBarrier.await(); //int result = mCyclicBarrier.await(2000, TimeUnit.MILLISECONDS); </span> // Log.e(TAG, "Thread num is " + threadName + " is over " + result); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } //catch (TimeoutException e) { // e.printStackTrace(); // <span style="color:#ff0000;">Log.e(TAG, "TimeoutException");</span> // } } }.start(); } }
执行结果:
E/TAG: Thread num is 0 is wait! E/TAG: Thread num is 1 is wait! E/TAG: Thread num is 2 is wait! E/TAG: Thread num is 2 is over E/TAG: Thread num is 0 is over E/TAG: Thread num is 1 is 4000 over可以看到,等3个都await后,才集体被唤醒,执行over。
其中带参数的await方法,是等待超时时间,如果等待超时,直接抛出TimeOutException。
4.Phaser
算是CountDownLatch和CyclicBarrier 的合体,但也有改进。举个栗子:一个任务有3个线程去并发执行,这个任务可以分为4个阶段,并且每个阶段结束,才能进行下个阶段。
那么new Phaser(3),就是三个线程并发执行。三个线程执行调用arriveAndAwaitAdvance()方法,这个方法会等待,直到执行arriveAndAwaitAdvance()方法到达3个后(意思就是当前阶段全部结束,可以进行下个阶段了),都被唤醒,继续执行。
测试代码:
private void initPhaser() { //三个线程来执行 int threads = 3; //4个阶段 final int phaser = 4; mPhaser = new Phaser(<span style="color:#ff0000;">threads</span>); for (int i = 0; i < 3; i++) { final String threadName = i + ""; new Thread() { @Override public void run() { super.run(); for (int phase = 0; phase < phaser; phase++) { Log.e(TAG, "Thread num is " + threadName + "phase is " + phase); <span style="color:#ff0000;">mPhaser.arriveAndAwaitAdvance();</span> } } }.start(); } }
执行结果:
E/TAG: Thread num is 0phase is 0 E/TAG: Thread num is 1phase is 0 E/TAG: Thread num is 2phase is 0 E/TAG: Thread num is 1phase is 1 E/TAG: Thread num is 2phase is 1 E/TAG: Thread num is 0phase is 1 E/TAG: Thread num is 1phase is 2 E/TAG: Thread num is 0phase is 2 E/TAG: Thread num is 2phase is 2 E/TAG: Thread num is 1phase is 3 E/TAG: Thread num is 2phase is 3 E/TAG: Thread num is 0phase is 3可以看到,arriveAndAwaitAdvance()方法,在到达设定值之前会一直等待。
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- 使用 Syncthing 在多个设备间同步文件
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- 科学知识:同步、异步、阻塞和非阻塞区别
- 同步文件备份工具 Super Flexible File Synchronizer Pro v4
- 探讨Ajax中同步与异步之间的区别
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- 解析C#多线程编程中异步多线程的实现及线程池的使用
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- 分享我在工作中遇到的多线程下导致RCW无法释放的问题
- C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法
- rsync命令使用总结