Java 并发编程之 Semaphore

Java juc About 3,163 words

作用

限制一定数量的线程去访问资源。

  1. 互斥锁:许可证为1时,可用作互斥锁。

  2. ATM取钱:许可证>1时,获得许可证的线程唤醒。

构造函数

permits:许可证数量

fair:是否公平

// nonfair fairness setting默认非公平
public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

acquire() 方法

请求获取许可证,可传入获取的数量。

release() 方法

释放许可证。

案例

互斥锁

public static void method1() {
    Semaphore semaphore = new Semaphore(1);
    for (int i = 0; i < 3; i++) {
        new Thread(() -> {
            try {
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 准备获取锁");
                semaphore.acquire();
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 已获得锁, 进行操作");
                TimeUnit.SECONDS.sleep(3);
                semaphore.release();
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 操作完毕, 释放锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

输出:

2020-01-18T20:42:30.597: 当前线程=Thread-1, 准备获取锁
2020-01-18T20:42:30.597: 当前线程=Thread-2, 准备获取锁
2020-01-18T20:42:30.597: 当前线程=Thread-1, 已获得锁, 进行操作
2020-01-18T20:42:30.597: 当前线程=Thread-0, 准备获取锁
2020-01-18T20:42:33.611: 当前线程=Thread-1, 操作完毕, 释放锁
2020-01-18T20:42:33.611: 当前线程=Thread-2, 已获得锁, 进行操作
2020-01-18T20:42:36.618: 当前线程=Thread-2, 操作完毕, 释放锁
2020-01-18T20:42:36.618: 当前线程=Thread-0, 已获得锁, 进行操作
2020-01-18T20:42:39.618: 当前线程=Thread-0, 操作完毕, 释放锁

线程竞争获取资源

public static void method2() {
    Semaphore semaphore = new Semaphore(3, true);
    for (int i = 0; i < 5; i++) {
        new Thread(() -> {
            try {
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 准备取钱操作");
                semaphore.acquire();
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 进入ATM间, 锁门, 取钱");
                TimeUnit.SECONDS.sleep(3);
                semaphore.release();
                System.out.println(LocalDateTime.now() + ": 当前线程=" + Thread.currentThread().getName() + ", 取完钱了, 开门, 走出ATM");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

输出:

2020-01-18T20:44:38.792: 当前线程=Thread-4, 准备取钱操作
2020-01-18T20:44:38.792: 当前线程=Thread-4, 进入ATM间, 锁门, 取钱
2020-01-18T20:44:38.792: 当前线程=Thread-3, 准备取钱操作
2020-01-18T20:44:38.792: 当前线程=Thread-3, 进入ATM间, 锁门, 取钱
2020-01-18T20:44:38.792: 当前线程=Thread-0, 准备取钱操作
2020-01-18T20:44:38.792: 当前线程=Thread-0, 进入ATM间, 锁门, 取钱
2020-01-18T20:44:38.792: 当前线程=Thread-2, 准备取钱操作
2020-01-18T20:44:38.792: 当前线程=Thread-1, 准备取钱操作
2020-01-18T20:44:41.792: 当前线程=Thread-4, 取完钱了, 开门, 走出ATM
2020-01-18T20:44:41.792: 当前线程=Thread-0, 取完钱了, 开门, 走出ATM
2020-01-18T20:44:41.792: 当前线程=Thread-2, 进入ATM间, 锁门, 取钱
2020-01-18T20:44:41.792: 当前线程=Thread-1, 进入ATM间, 锁门, 取钱
2020-01-18T20:44:41.792: 当前线程=Thread-3, 取完钱了, 开门, 走出ATM
2020-01-18T20:44:44.799: 当前线程=Thread-2, 取完钱了, 开门, 走出ATM
2020-01-18T20:44:44.799: 当前线程=Thread-1, 取完钱了, 开门, 走出ATM
Views: 2,214 · Posted: 2020-01-18

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓


Today On History
Browsing Refresh