Semaphore重點文法
- availablePermits():判斷是否有權限
- acquire():獲得一個信号,阻塞線程,可被中斷
- release():釋放一個信号
- acquireUninterruptibly():獲得一個信号,阻塞線程,不可被中斷
代碼示例
每次隻允許2個線程執行
public class SemaphoreThread {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
// 建立一個緩存線程池
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
es.submit(new Thread(() -> {
String name = Thread.currentThread().getName();
try {
semaphore.acquire();
System.out.println(LocalDateTime.now().toLocalTime()+" "+name + "開始執行");
Thread.sleep(1000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
}
// 關閉線程池
es.shutdown();
}
}
輸出:
13:42:11.763 pool-1-thread-2開始執行
13:42:11.763 pool-1-thread-1開始執行
13:42:12.764 pool-1-thread-3開始執行
13:42:12.764 pool-1-thread-5開始執行
13:42:13.764 pool-1-thread-6開始執行
13:42:13.764 pool-1-thread-4開始執行
13:42:14.764 pool-1-thread-9開始執行
13:42:14.764 pool-1-thread-10開始執行
13:42:15.765 pool-1-thread-7開始執行
13:42:15.765 pool-1-thread-8開始執行
從輸出日志可以看出,每秒隻有2個線程在執行
控制兩個線程執行順序
public class SemaphoreThread {
public static void main(String[] args) {
// 設定公平鎖
Semaphore semaphore = new Semaphore(1,true);
// 建立一個緩存線程池
ExecutorService es = Executors.newCachedThreadPool();
es.submit( new Thread(() -> {
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
try {
semaphore.acquire();
System.out.println(LocalDateTime.now().toLocalTime()+" "+name + "正在工作");
Thread.sleep(1000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
es.submit( new Thread(() -> {
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
try {
semaphore.acquire();
System.out.println(LocalDateTime.now().toLocalTime()+" "+name + "正在工作");
Thread.sleep(100);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
// 關閉線程池
es.shutdown();
}
}
輸出:
13:45:11.661 pool-1-thread-1正在工作
13:45:12.662 pool-1-thread-2正在工作
13:45:12.763 pool-1-thread-1正在工作
13:45:13.763 pool-1-thread-2正在工作
13:45:13.863 pool-1-thread-1正在工作
13:45:14.864 pool-1-thread-2正在工作
13:45:14.965 pool-1-thread-1正在工作
13:45:15.965 pool-1-thread-2正在工作
13:45:16.066 pool-1-thread-1正在工作
13:45:17.067 pool-1-thread-2正在工作
13:45:17.167 pool-1-thread-1正在工作
13:45:18.168 pool-1-thread-2正在工作
13:45:18.268 pool-1-thread-1正在工作
13:45:19.268 pool-1-thread-2正在工作
13:45:19.368 pool-1-thread-1正在工作
13:45:20.369 pool-1-thread-2正在工作
13:45:20.470 pool-1-thread-1正在工作
13:45:21.470 pool-1-thread-2正在工作
13:45:21.570 pool-1-thread-1正在工作
13:45:22.571 pool-1-thread-2正在工作
從輸出日志可以看出,兩個線程交替執行,這裡的關鍵是設定了信号量公平鎖