Semaphore类是控制并发的数量的并发类,主要作用就是限制线程并发的数量,如果不限制线程并发的数量,cpu的资源很快就耗尽了,每个线程访问的效率也会比较低下,因为cpu要把时间片分配给不同的线程对象,而且上下文切换也要耗时,所以限制线程数量非常重要。
比如说一个生产商,发布了10个代理销售许可,所以最多只有10个代理商来获取其中的一个许可,限制到申请数量,这也就是Semaphore要达到的目的。
使用场景一:实现线程互斥同步,同一时间就一个线程对一个方法进行访问。
package cn.wzy.maintest;
import java.util.Date;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
private Semaphore semaphore = new Semaphore(1);
public void method() {
try {
semaphore.acquire(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "," + new Date().getTime());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release(1);
}
}
说明:new Semaphore(n)的构造参数代表生成n个许可证,acquire(m)代表访问一次需要m许可证,release(k)代表释放k个许可证,上面的代码指的是发布1个许可,然后每次访问需要1个许可,那就代表同一时间只会有一个线程访问method方法。
测试及结果:新建10个线程,输出线程执行情况。
package cn.wzy.maintest;
public class Main {
public static void main(String[] args) {
SemaphoreTest service = new SemaphoreTest();
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(()->
service.method()
);
threads[i].setName("thread:" + i);
threads[i].start();
}
while (Thread.activeCount() > 2) {
Thread.yield();
}
}
}
thread:0,1528684590813
thread:1,1528684591813
thread:2,1528684592813
thread:3,1528684593813
thread:4,1528684594813
thread:5,1528684595814
thread:6,1528684596814
thread:7,1528684597814
thread:8,1528684598814
thread:9,1528684599815
Process finished with exit code 0
结果显示同一时间只有一个线程访问method。
使用场景二:控制线程访问的数量,此时线程不会实现互斥同步,只是减少线程的访问数量,线程之间还是会有线程安全问题。
package cn.wzy.maintest;
import java.util.Date;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
private Semaphore semaphore = new Semaphore(10);
public void method() {
try {
semaphore.acquire(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "," + new Date().getTime());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release(2);
}
}
thread:1,1528684955678
thread:0,1528684955679
thread:2,1528684955679
thread:3,1528684955679
thread:4,1528684955679
thread:5,1528684956678
thread:6,1528684956679
thread:7,1528684956679
thread:8,1528684956679
thread:9,1528684956679
Process finished with exit code 0
结果说明:最开始只是有10个许可证,然而每次访问需要2个许可证,也就是说同一时间最多只有5个线程同时访问。