信号量:semaphore

2019-05-06  本文已影响0人  topshi

允许多个线程同时访问:信号量semaphore

信号量为多线程协作提供了更为强大的控制方法。无论是内部锁synchronized还是重入锁ReentranctLock,一次只允许一个线程访问资源,而信号量可以指定多个线程同时访问某一个资源。
信号量的构造函数:

    public Semaphore(int permits) {
        this.sync = new Semaphore.NonfairSync(var1);
    }

    public Semaphore(int permits, boolean fair) {
        this.sync = (Semaphore.Sync)(var2 ? new Semaphore.FairSync(var1) : new Semaphore.NonfairSync(var1));
    }

permiits参数指定信号量的准入数,也就是同时能申请多少个许可。当一个线程只允许申请一次时,相当于指定多少个线程可以访问某一个资源。fair参数指定是否公平。
信号量主要逻辑方法:

public void acquire() throws InterruptedException 
public void acquireUninterruptibly() 
public boolean tryAcquire() 
public boolean tryAcquire(long time, TimeUnit unit) throws InterruptedException 
public void release()

Semaphore示例

package semaphore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @Time : 2019/05/06 下午 02:47
 * @Author : xiuc_shi
 **/
public class SemaphoreDemo implements Runnable {
    final Semaphore semaphore = new Semaphore(5);
    @Override
    public void run() {
        try {
            semaphore.acquire();
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getId() + " Done");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            semaphore.release();
        }
    }
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(20);
        final SemaphoreDemo demo = new SemaphoreDemo();
        for(int i = 0;i < 20;i++){
            es.execute(demo);
        }
        es.shutdown();
    }
}

信号量用完必须释放,和释放锁一样,否则可用的信号量会越来越少。

应用场景

Semaphore可以用于做流量控制,特别是公用资源有限的应用场景,比如数据库连接。假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发地读取,但是如果读到内存后,还需要存储到数据库中,而数据库的连接数只有10个,这时我们必须控制只有10个线程同时获取数据库连接保存数据,否则会报错无法获取数据库连接。这个时候,就可以使用Semaphore来做流量控制。(摘自《java并发编程的艺术》)

上一篇下一篇

猜你喜欢

热点阅读