多线程控制、同步的几个实用的类

多个线程之间的控制,最基本的就是相互之间的wait(),notify()等。其实java.util.concurrent类中已经有了好多同步辅助类,需要的时候感觉还是很好用的。用法整理一下,走起!

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 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()方法,在到达设定值之前会一直等待。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值