多线程开发常见问题汇总
1. Thread.UncaughtExceptionHandlerUncaughtExceptionHandler是一个接口,用于处理线程因未捕获异常而突然终止的情况。
虽然,通常都会在线程执行的代码中加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://blog.csdn.net/weixin_42373241/article/details/139441473
页:
[1]