JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

66.java并发编程之Semaphore和CountDownLatch使用

wys521 2024-11-06 20:36:03 精选教程 39 ℃ 0 评论

文章目录

      • 一、前言
      • 二、CountDownLatch
        • 2.1、CountDownLatch说明
        • 2.2、CountDownLatch代码
      • 三、Semaphore
        • 3.1、Semaphore代码
      • 四、总结

一、前言

Semaphore(信号量),用于做限流处理,比如说同时只允许五个人访问,超过五个人访问就需要等待,类似这样的需求,下面的案例可以看出执行是五个五个的执行,等上一个五个执行完了,才会执行下一个
CountDownLatch是配合Semaphore使用的,CountDownLatch是进行控制线程执行完,如果线程执行不完,则处于线程等待的状态。

二、CountDownLatch

2.1、CountDownLatch说明

对于CountDownLatch,其他线程为游戏玩家,比如英雄联盟,主线程为控制游戏开始的线程。在所有的玩家都准备好之前,主线程是处于等待状态的,也就是游戏不能开始。当所有的玩家准备好之后,下一步的动作实施者为主线程,即开始游戏。
我们使用代码模拟这个过程,我们模拟了三个玩家,在三个玩家都准备好之后,游戏才能开始。代码的输出结果为:

正在等待所有玩家准备好
player0 已经准备好了, 所使用的时间为 1.235s

player2 已经准备好了, 所使用的时间为 1.279s

player3 已经准备好了, 所使用的时间为 1.358s

player1 已经准备好了, 所使用的时间为 2.583s

开始游戏

2.2、CountDownLatch代码

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(4);
        for(int i = 0; i < latch.getCount(); i++){
            new Thread(new MyThread(latch), "player"+i).start();
        }
        System.out.println("正在等待所有玩家准备好");
        latch.await();
        System.out.println("开始游戏");
    }

    private static class MyThread implements Runnable{
        private CountDownLatch latch ;

        public MyThread(CountDownLatch latch){
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                Random rand = new Random();
                int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000;//产生1000到3000之间的随机整数
                Thread.sleep(randomNum);
                System.out.println(Thread.currentThread().getName()+" 已经准备好了, 所使用的时间为 "+((double)randomNum/1000)+"s");
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

三、Semaphore

3.1、Semaphore代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class UseSemaphore {

    public static void main(String[] args) {
        // 线程池  
        ExecutorService exec = Executors.newCachedThreadPool();
        // 只能5个线程同时访问  
        final Semaphore semp = new Semaphore(5);
        // 模拟20个客户端访问  
        for (int index = 0; index < 20; index++) {
            final int NO = index;
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        // 获取许可  
                        semp.acquire();
                        System.out.println("Accessing: " + NO);
                        //模拟实际业务逻辑
                        Thread.sleep((long) (Math.random() * 10000));
                        // 访问完后,释放  
                        semp.release();
                    } catch (InterruptedException e) {
                    }
                }
            };
            exec.execute(run);
        }

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //System.out.println(semp.getQueueLength());
        // 退出线程池
        exec.shutdown();
    }
}  

四、总结

CountDownLatch和Semaphore的区别在于前者是控制保证每个线程执行完毕,后者是控制流量,当资源有限的时候进行控制执行的速度来达到控制并发的作用。其实两者是可以联合起来进行一块使用来达到控制并发的目的。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表