用Semaphore信号量控制线程执行

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正在工作

从输出日志可以看出,两个线程交替执行,这里的关键是设置了信号量公平锁

你可能感兴趣的:(java基础)