Semaphore信号量 协调多线程合理使用公共资源

Semaphore信号量 协调多线程合理使用公共资源


GitHub: link. 欢迎star

注意:本篇博客风格(不多比比就是撸代码!!!)

一、使用场景

  • 多线程环境下,借助Semaphore信号量协调各个线程, 以保证它们能够正确、合理的使用公共资源。
  • 初始化,许可数量:new Semaphore(permits);
  • 获取许可证:semaphore.acquire();
  • 释放许可,增加许可数量:semaphore.release();

二、SemaphoreTest.java

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;

/**
 * @author Andon
 * 2022/5/20
 */
@Slf4j
public class SemaphoreTest {

    private static int permits = 3;
    private static Semaphore semaphore = new Semaphore(permits);

    @Test
    public void semaphore() throws Exception {
        int num = 5;
        log.info("有{}个位置可以做核酸", permits);
        log.info("来了{}个人做核酸", num);

        List<CompletableFuture<Void>> completableFutures = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            semaphore.acquire();
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                try {
                    long stop = (long) (Math.random() * 10 + 1);
                    log.info("{}开始做核酸,耗时{}秒", Thread.currentThread().getName(), stop);
                    Thread.sleep(stop * 1000);
                } catch (Exception ignored) {
                } finally {
                    log.info("{}做完核酸准备离开", Thread.currentThread().getName());
                    semaphore.release();
                    log.info("{}已经离开了!!", Thread.currentThread().getName());
                }
            });
            completableFutures.add(completableFuture);
        }
        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
        completableFuture.join();
    }
}

三、测试

在这里插入图片描述

附加:中断分片线程

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Andon
 * 2022/5/20
 */
@Slf4j
public class ThreadTnterruptTest {

    /**
     * 中断分片线程 测试
     */
    @Test
    public void interruptTest() throws ExecutionException, InterruptedException {
        List<Thread> threads = new ArrayList<>();

        ExecutorService executorService = Executors.newFixedThreadPool(8);
        List<Future<?>> futures = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            int finalI = i + 1;
            Future<?> future = executorService.submit(() -> {
                Thread thread = Thread.currentThread();
                threads.add(thread);
                try {
                    log.info("[{}] - thread start!! finalI={}", thread.getId(), finalI);
                    Thread.sleep(finalI * 1000);
                    threadCheck();
                    if (finalI == 3) {
                        throw new Exception("Exception");
                    }
                    log.info("[{}] - thread end!! finalI={}", thread.getId(), finalI);
                } catch (Exception e) {
                    log.info("[{}] - thread interrupt!!", thread.getId());
                    interrupt(threads);
                }
            });
            futures.add(future);
        }
        for (Future<?> future : futures) {
            future.get();
        }
        log.info("end!!");
    }

    /**
     * 线程检查
     * <p>
     * 在线程中计划中断的地方执行
     */
    public void threadCheck() throws InterruptedException {
        Thread.sleep(10);
    }

    /**
     * 中断线程
     * <p>
     * 会在线程检查代码执行时,抛出异常来中断线程
     */
    public void interrupt(List<Thread> threads) {
        for (Thread thread : threads) {
            thread.interrupt();
        }
    }
}

GitHub: link. 欢迎star

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值