无论是内部锁synchronized,还是重入锁ReentrantLock,一次都只允许一个线程访问一个资源,而信号量却可以实现指定多个线程同时访问某一个资源。

1.构造函数

public Semaphore(int permits)

public Semaphore(int permits,boolean fair); //第二个参数指定是否公平,参见公平锁

在构造信号量时,必须指定信号量的准入数permits,即同时能申请多少个许可。当一个线程只能申请一个许可时,相当于permits指定了同时有多少个线程可以访问某一个资源。

2.常用方法

2.1、acquire():尝试获得一个准入的许可,若无法获得,则线程会等待,直到有线程释放一个许可或者该线程被中断。

2.2、acquireUninterruptibly():与acquire()类似,但它不响应中断!

2.3、tryAcquire():尝试获得一个许可,成功返回true,失败则返回false,它不会进行等待,立即返回。

2.4、tryAcquire(long time,TimeUnit unit):在time时长内尝试获得一个许可。

2.5、release():用于在线程访问资源结束后,释放一个许可。

2.6、当信号量的数量上限permits==1时,Semaphore可当做锁来使用。

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Semaphore; 
 
/** 
 * Created by Liuxd on 2018-07-18. 
 */ 
public class TestSemaphone implements Runnable { 
 
    private final Semaphore semaphore = new Semaphore(5); 
 
    public void run() { 
        try { 
            /** 
             * 尝试获得一个许可,不断尝试,直到获得许可 
             */ 
            semaphore.acquire(); 
 
            /** 
             * 模拟耗时操作 
             */ 
            Thread.sleep(2000); 
 
            System.out.println(Thread.currentThread().getId() + ":" + Thread.currentThread().getName() + " done!"); 
 
            /** 
             * 释放许可 
             */ 
            semaphore.release(); 
 
 
        } catch (InterruptedException e) { 
 
            e.printStackTrace(); 
 
        } finally { 
 
        } 
 
    } 
 
    public static void main(String[] argv) throws InterruptedException { 
 
        TestSemaphone r = new TestSemaphone(); 
 
        ExecutorService exec = Executors.newFixedThreadPool(20); 
 
        for (int i = 0; i < 20; i++) { 
 
            exec.submit(r); 
 
        } 
 
        exec.shutdown(); 
 
    } 
 
} 
 
 

参考:

CSDN


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Java 实现重试机制