编程语言
首页 > 编程语言> > 【JAVA核心知识】15.3:线程控制器Semaphore

【JAVA核心知识】15.3:线程控制器Semaphore

作者:互联网

Semaphore

简介

多用于线程多于资源下的资源控制的线程控制器。很像锁同步,和锁同步不同的是锁锁定一个资源,同时只能有一个线程操作这个资源。而Semaphore则是锁定一批资源。同时只允许指定数目的线程执行操作。
也与线程池有一定相似。不同的是线程池等待的线程未运行,而这个线程已经在运行并且在争夺。
适用于资源量小于线程量的情况。比如一个连接只允许同时有10个线程连接,现在有100个线程要执行这个连接操作,那么就可以用Semaphore进行控制。

常用方法

示例

package sync;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    public static void main(String[] args) {
        final Semaphore s = new Semaphore(2);  // 入参为2则为正常的3任务调2个许可流程,为1可验证无需获得许可便可释放许可
        Runnable r1 = new Runnable() {
            
            @Override
            public void run() {
                try {
                    System.out.println("1号请求资源 - " + showNow());
                    s.acquire();
                    System.out.println("1号获得资源 - " + showNow());
                    System.out.println("1号开始工作 - " + showNow());
                    Thread.sleep(5000);
                    System.out.println("1号工作完毕,开始释放资源 - " + showNow());
                    s.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        Runnable r2 = new Runnable() {
            
            @Override
            public void run() {
                try {
//                    Thread.sleep(200);  // 保证执行顺序是1.2.3
                    System.out.println("2号请求资源 - " + showNow());
                    s.acquire();  // 如果把这个地方注释掉,并打开保证释放顺序的代码并设置许可为一个,运行会发现1号先持有资源工作,然后2无需获得许可就可释放许可,使得3在1未执行完毕释放许可时便获得许可开始执行
                    System.out.println("2号获得资源 - " + showNow());
                    System.out.println("2号开始工作 - " + showNow());
                    Thread.sleep(1000);
                    System.out.println("2号工作完毕,开始释放资源 - " + showNow());
                    s.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        Runnable r3 = new Runnable() {
            
            @Override
            public void run() {
                try {
//                    Thread.sleep(500);// 保证执行顺序是1.2.3
                    System.out.println("3号请求资源 - " + showNow());
                    s.acquire();
                    System.out.println("3号获得资源 - " + showNow());
                    System.out.println("3号开始工作 - " + showNow());
                    Thread.sleep(1000);
                    System.out.println("3号工作完毕,开始释放资源 - " + showNow());
                    s.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        new Thread(r1).start();
        new Thread(r2).start();
        new Thread(r3).start();
    }

    private static String showNow(){
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        return sdf.format(new Date());
    }
    
}

运行结果:

2号请求资源 - 17:23:48.107
1号请求资源 - 17:23:48.107
2号获得资源 - 17:23:48.107
3号请求资源 - 17:23:48.107
2号开始工作 - 17:23:48.107
1号获得资源 - 17:23:48.107
1号开始工作 - 17:23:48.107
2号工作完毕,开始释放资源 - 17:23:49.107
3号获得资源 - 17:23:49.108
3号开始工作 - 17:23:49.108
3号工作完毕,开始释放资源 - 17:23:50.108
1号工作完毕,开始释放资源 - 17:23:53.107

PS:
【JAVA核心知识】系列导航 [持续更新中…]
上篇导航:15.2:线程控制器CyclicBarrier
下篇预告:16:volatile关键字
欢迎关注…

标签:15.3,JAVA,许可,23,获得,线程,println,showNow
来源: https://blog.csdn.net/yue_hu/article/details/117749530