zoukankan      html  css  js  c++  java
  • java并发编程之Semaphore

    信号量(Semaphore)。有时被称为信号灯。是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们可以正确、合理的使用公共资源。


    一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要。在许可可用前会堵塞每个 acquire(),然后再获取该许可。每个 release() 加入一个许可。从而可能释放一个正在堵塞的获取者。

    可是。不使用实际的许可对象,Semaphore 仅仅对可用许可的号码进行计数,并採取对应的行动。拿到信号量的线程能够进入代码。否则就等待。通过acquire()和release()获取和释放訪问许可。

    package com.lala.shop;
    
    import java.time.Duration;
    import java.time.Instant;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.TimeUnit;
    
    public class SemaphoreDemo 
    {
    	/**
    	 * 这里演示了一个样例:十个人一起上厕所
    	 * 假设一次仅仅能一个人上厕所,则总共须要时间:1+2+3+4+5+6+7+8+9+10=55分钟
    	 * 假设一次能10个人一起上厕所。则总共须要时间:10分钟
    	 */
    	static void demonstration(int num) throws Exception
    	{
    		String[] users = {"刘梅","夏东海","夏雪","刘星","夏雨","爷爷","姥姥","玛丽","胡一统","林宁"};
    		
    		CountDownLatch cdl = new CountDownLatch(users.length);
    		
    		Integer[] times = {1,2,3,4,5,6,7,8,9,10};
    		List<Integer> timeList = Arrays.asList(times);
    		Collections.shuffle(timeList);
    		
    		Semaphore sph = new Semaphore(num);
    		
    		ExecutorService runner = Executors.newCachedThreadPool();
    		
    		Instant start = Instant.now();
    		
    		for(int i=0; i<users.length; i++)
    		{
    			final int index = i;
    			runner.submit(() -> {
    				try 
    				{
    					//拿到信号灯,准备上厕所
    					sph.acquire();
    					
    					long time = timeList.get(index);
    					
    					TimeUnit.SECONDS.sleep(time);
    					
    					System.out.println(users[index] + "如厕完成。共花费时间:" + time);
    					cdl.countDown();
    					//事情已经办完,释放信号灯
    					sph.release();
    				} catch (Exception e) 
    				{
    					e.printStackTrace();
    				}
    			});
    		}
    		runner.shutdown();
    		
    		cdl.await();
    		
    		Instant end = Instant.now();
    		Duration speed = Duration.between(start, end);
    		long seconds = speed.getSeconds();//秒表示   
    		System.out.println("所有上完厕所(一次仅仅能有" + num + "人如厕),总共花了时间:" + seconds);
    	}
    	public static void main(String[] args) throws Exception
    	{
    		demonstration(5);
    	}
    }
    

    假设调用方式为:

    demonstration(5);

    则,输出为:

    夏雪如厕完成。共花费时间:1
    夏雨如厕完成,共花费时间:3
    刘星如厕完成,共花费时间:4
    爷爷如厕完成,共花费时间:6
    夏东海如厕完成,共花费时间:8
    刘梅如厕完成,共花费时间:9
    胡一统如厕完成。共花费时间:2
    玛丽如厕完成,共花费时间:7
    林宁如厕完成,共花费时间:5
    姥姥如厕完成,共花费时间:10
    所有上完厕所(一次仅仅能有5人如厕),总共花了时间:13


    假设调用方式为:

    demonstration(1);

    则,输出为:

    刘梅如厕完成,共花费时间:10
    夏东海如厕完成,共花费时间:6
    夏雪如厕完成,共花费时间:3
    刘星如厕完成。共花费时间:9
    夏雨如厕完成。共花费时间:8
    爷爷如厕完成。共花费时间:4
    姥姥如厕完成,共花费时间:1
    玛丽如厕完成。共花费时间:5
    胡一统如厕完成,共花费时间:7
    林宁如厕完成,共花费时间:2
    所有上完厕所(一次仅仅能有1人如厕),总共花了时间:55


    假设调用方式为

    demonstration(10); 则输出为:

    夏雨如厕完成,共花费时间:1
    夏东海如厕完成,共花费时间:2
    爷爷如厕完成,共花费时间:3
    刘星如厕完成。共花费时间:4
    刘梅如厕完成,共花费时间:5
    胡一统如厕完成。共花费时间:6
    林宁如厕完成,共花费时间:7
    姥姥如厕完成,共花费时间:8
    玛丽如厕完成,共花费时间:9
    夏雪如厕完成,共花费时间:10
    所有上完厕所(一次仅仅能有10人如厕)。总共花了时间:10

  • 相关阅读:
    .NET基础示例系列之十二:DLLImport
    .NET基础示例系列之二:Socket
    Qt之msvcversion.conf loaded but QMAKE_MSC_VER isn‘t set
    Ubuntu安装sshd
    Quick工程设置exe图标
    git修改文件之后上传
    VS里打开Qt的pro工程
    QtQWebEngineView显示百度网页
    在gitte建立新仓库并上传本地工程
    Qt的qDebug打印加颜色
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6882697.html
Copyright © 2011-2022 走看看