请看文档注释:
package com.abc.test
import org.junit.Test
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
class SemaphoreTest {
var pools: ExecutorService = Executors.newFixedThreadPool(10)
/**
* Semaphore 意为许可。主要用来限制多线程对资源的访问。
* 只有拿到许可才可以访问资源.
* acquire()会取走一个许可,release()会还回一个许可.
* 如果此时剩余许可为0调用其acquire方法会导致当前线程阻塞直到一个许可可用。
* 我们创建只有一个许可的Semaphore对象。
* 然后启动10个同样的线程,每个线程都调用acquire()和release(),在中间sleep 2秒。
* 然后会发现这些线程会依次执行acquire()到release()之间的block:只有在前一个线程的block执行完毕之后才会执行下一个线程的block
* 可以注释掉 semaphore.acquire()和 semaphore.release()
* 对比下2者的输出.
*/
@Test
fun testSemaphore() {
var semaphore = Semaphore(1)
1.rangeTo(20).forEach {
pools.execute {
println("before acquire:$it");
semaphore.acquire();
println("start running:$it");
Thread.sleep(100);
println("finish running:$it");
semaphore.release();
}
}
pools.shutdown();
pools.awaitTermination(100, TimeUnit.SECONDS);
}
/**
* 我们创建2个许可的Semaphore对象。
* 然后启动10个同样的线程,每个线程都调用acquire()和release(),在中间sleep 2秒。
* 然后会发现同时有2个线程会执行acquire()到release()之间的block:
* 可以和上面的代码对比下2者的输出.
*/
@Test
fun testSemaphore2() {
var semaphore = Semaphore(2)
1.rangeTo(20).forEach {
pools.execute {
// System.out.println("before acquire:$it");
semaphore.acquire();
System.out.println("start running:$it");
Thread.sleep(100);
System.out.println("finish running:$it");
semaphore.release();
}
}
pools.shutdown();
pools.awaitTermination(100, TimeUnit.SECONDS);
}
/**
* 我们创建1个许可的Semaphore对象。
* tryAcquire():尝试去获取许可,如果失败返回false,成功为true.
* 我们同时启动20个线程来抢这个许可
* 读者可以多次运行然后仔细观察结果。
* 也可以注释掉73行的输出后观察结果,请仔细体会结果为什么相差这么大.
*/
@Test
fun testTryAcquire() {
var semaphore = Semaphore(1)
1.rangeTo(20).forEach {
pools.execute {
if (semaphore.tryAcquire()) {
//73行代码
System.out.println("start running:$it");
semaphore.release();
} else {
System.out.println("no perimit: $it");
}
}
}
pools.shutdown();
pools.awaitTermination(100, TimeUnit.SECONDS);
}
}