写点什么

多线程开发常见问题汇总

  • 2025-04-08
    福建
  • 本文字数:2687 字

    阅读完需:约 9 分钟

1. Thread.UncaughtExceptionHandler


UncaughtExceptionHandler‌ 是一个接口,用于处理线程因未捕获异常而突然终止的情况。


虽然,通常都会在线程执行的代码中加 try...catch 来捕获异常,那么如果某些异常没有被 catch 住(比如,线程突然死掉了)那么我们将不知道发生了什么。因此,给每个现在设置一个未捕获异常处理器很有必要。


@Slf4jpublic class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {    @Override    public void uncaughtException(Thread t, Throwable e) {        log.info("线程异常: {}", t.getName(), e);    }}

public static void main(String[] args) { // 设置全局默认的未捕获异常处理器 Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Thread thread = new Thread(() -> { int a = 1 / 0; }); // 给某个线程设置自己的未捕获异常处理器 thread.setUncaughtExceptionHandler(((t, e) -> { System.out.println("线程执行异常!线程名称: " + t.getName()); logger.error("线程执行异常!名称: {}", t.getName(), e); }));
thread.start();}
复制代码


通常我们采用线程池的方式使用线程,下面是在线程池中使用方式


public static void main(String[] args) {    ExecutorService executorService = Executors.newFixedThreadPool(3, new ThreadFactory() {        @Override        public Thread newThread(Runnable r) {            Thread t = new Thread(r);            t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());            return t;        }    });
executorService.execute(new Runnable() { @Override public void run() { int a = 1 / 0; } });}
复制代码


2. CountDownLatch(倒计时)


CountDownLatch 是 Java 中的一个同步工具类,它允许一个或多个线程等待其他线程完成操作。


public static void main(String[] args) {    ExecutorService executorService = Executors.newFixedThreadPool(3, new ThreadFactory() {        @Override        public Thread newThread(Runnable r) {            Thread t = new Thread(r);            t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());            return t;        }    });
int count = 10; // 10个任务 CountDownLatch latch = new CountDownLatch(count); for (int i = 0; i < count; i++) {// executorService.execute(()->{// try {//// } catch (Exception ex) {//// } finally {// latch.countDown();// }//// }); executorService.execute(new MyTask(latch)); }
try { latch.await(); // 等待所有异步任务执行完成 } catch (InterruptedException e) { throw new RuntimeException(e); }
// 执行后续处理逻辑}
static class MyTask implements Runnable {
private CountDownLatch latch;
public MyTask(CountDownLatch latch) { this.latch = latch; }
@Override public void run() { try {
} catch (Exception e) {
} finally { latch.countDown(); } }}
复制代码


3. Semaphore(信号量)


Semaphore 是一个用于控制同时访问特定资源的线程数量的同步工具。它通过维护一个许可集来管理对资源的访问。线程在访问资源之前必须从信号量中获取许可,访问完成后释放许可。如果没有可用的许可,线程将被阻塞,直到有可用的许可为止。


/** * 控制并发执行的任务数量 */public static void main(String[] args) {    ExecutorService executorService = Executors.newFixedThreadPool(3);
Semaphore semaphore = new Semaphore(10);
// 模拟100个附件同时上传 for (int i = 0; i < 100; i++) { executorService.execute(()->{ try { semaphore.acquire(); upload(); } catch (Exception e) {
} finally { semaphore.release(); } }); } executorService.shutdown();}
/** * 附件上传操作 */public static void upload() { // 假设,最多同时处理10个附件,太多的话可能会内存溢出,为了保护它,不让它挂掉,我们可以控制并发请求数量 // ......}
复制代码


上面的例子,我们在调用端限制并发请求数来达到保护被调用方的目的,其实也可以写在被调用端,效果是一样的,在调用方和被调用方其中一方做控制就行。


4. Redisson 分布式锁和同步器

Redisson 是 Redis 的 Java 客户端,在分布式环境下,Redission 实现了 Semaphore 和 CountDownLatch。

https://redisson.org/docs/data-and-services/locks-and-synchronizers/



<dependency>    <groupId>org.redisson</groupId>    <artifactId>redisson</artifactId>    <version>3.41.0</version></dependency>
复制代码


Semaphore 基本用法


RSemaphore semaphore = redisson.getSemaphore("mySemaphore");
// acquire single permitsemaphore.acquire();
// or acquire 10 permitssemaphore.acquire(10);
// or try to acquire permitboolean res = semaphore.tryAcquire();
// or try to acquire permit or wait up to 15 secondsboolean res = semaphore.tryAcquire(15, TimeUnit.SECONDS);
// or try to acquire 10 permitboolean res = semaphore.tryAcquire(10);
// or try to acquire 10 permits or wait up to 15 secondsboolean res = semaphore.tryAcquire(10, 15, TimeUnit.SECONDS);if (res) { try { ... } finally { semaphore.release(); }}
复制代码


CountDownLatch 基本用法


RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch");
latch.trySetCount(1);// await for count downlatch.await();
// in other thread or JVMRCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch");latch.countDown();
复制代码


文章转载自:废物大师兄

原文链接:https://www.cnblogs.com/cjsblog/p/18641357

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
多线程开发常见问题汇总_多线程_量贩潮汐·WholesaleTide_InfoQ写作社区