多线程并发工具之Semaphore信号量

 Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。就这一点而言,单纯的synchronized 关键字是实现不了的。

那么semaphore最主要的方法就是acquire和release,简单点说就是拿到可以执行的线程数量和释放可以执行的线程数量。

多线程并发工具之Semaphore信号量_第1张图片

上代码,改代码实现了基本信号量的用法。

package concurrent.tools;

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

public class SemaphoreService {

    private static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    private Semaphore semaphore = new Semaphore(9);// 同步关键类,构造方法传入的数字是多少,则同一个时刻,只运行多少个进程同时运行制定代码

    public void doSomething() {
        try {
            /**
             * 在 semaphore.acquire() 和 semaphore.release()之间的代码,同一时刻只允许制定个数的线程进入,
             * 因为semaphore的构造方法是1,则同一时刻只允许一个线程进入,其他线程只能等待。
             * */
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + ":doSomething start-" + getFormatTimeStr());
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ":doSomething end-" + getFormatTimeStr());
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static String getFormatTimeStr() {
        return sf.format(new Date());
    }

    public int availablePermits() { // 查看可用通路数
        return semaphore.availablePermits();
    }

    public static void main(String args[]) {
        SemaphoreService service = new SemaphoreService();
        for (int i = 0; i < 10; i++) {
            MyThread t = new MyThread("thread" + (i + 1), service);
            t.start();// 这里使用 t.run() 也可以运行,但是不是并发执行了 
        }
    }
}

class MyThread extends Thread {
    private SemaphoreService service;

    public MyThread(String name, SemaphoreService service) {
        this.setName(name);
        this.service = service;
    }

    @Override
    public void run() {
        this.service.doSomething();
    }
}

扩展下其他的方法

Semaphore(int permits, boolean fair)   permites 参数是认证许可数量,fair 参数意思是否公平,获得锁的顺序与线程启动顺序有关,就是公平,先启动的线程,先获得锁。isFair 不能100% 保证公平,只能是大概率公平。

acquire (int)获取许可证,参数int 获取许可的数量,如果不传则则为1。

acquireUninterruptibly (int)持续获取许可证,当许可证不足持续等待不会抛异常,不建议使用。可能会导致线程堆积过多而挂机起不到自我保护。

 tryAcquire() 、 tryAcquire(int permits)、 tryAcquire(int permits , long timeout , TimeUint unit) 的使用:

tryAcquire 方法,是 acquire 的扩展版,tryAcquire 作用是尝试得获取通路,如果未传参数,就是尝试获取一个通路,如果传了参数,就是尝试获取 permits 个 通路 、在指定时间 timeout  内 尝试 获取 permits 个通路。

release 的用法与acquire相反,不再做多解释。

注意Semaphore(int permits) 是控制线程进入指定方法并发的数量。aquire是拿去许可证的数量。

 

 

你可能感兴趣的:(多线程实战,多线程,并发编程)