1. Thread.UncaughtExceptionHandler
UncaughtExceptionHandler 是一个接口,用于处理线程因未捕获异常而突然终止的情况。
虽然,通常都会在线程执行的代码中加try…catch来捕获异常,那么如果某些异常没有被catch住(比如,线程突然死掉了)那么我们将不知道发生了什么。因此,给每个现在设置一个未捕获异常处理器很有必要。
@Slf4jpublic class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {@Overridepublic 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();}@Slf4j public 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(); }@Slf4j public 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() {@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r);t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());return t;}});executorService.execute(new Runnable() {@Overridepublic void run() {int a = 1 / 0;}});}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; } }); }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() {@Overridepublic 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;}@Overridepublic void run() {try {} catch (Exception e) {} finally {latch.countDown();}}}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(); } } }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个附件,太多的话可能会内存溢出,为了保护它,不让它挂掉,我们可以控制并发请求数量// ......}/** * 控制并发执行的任务数量 */ 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个附件,太多的话可能会内存溢出,为了保护它,不让它挂掉,我们可以控制并发请求数量 // ...... }/** * 控制并发执行的任务数量 */ 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><dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.41.0</version> </dependency><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();}}RSemaphore semaphore = redisson.getSemaphore("mySemaphore"); // acquire single permit semaphore.acquire(); // or acquire 10 permits semaphore.acquire(10); // or try to acquire permit boolean res = semaphore.tryAcquire(); // or try to acquire permit or wait up to 15 seconds boolean res = semaphore.tryAcquire(15, TimeUnit.SECONDS); // or try to acquire 10 permit boolean res = semaphore.tryAcquire(10); // or try to acquire 10 permits or wait up to 15 seconds boolean res = semaphore.tryAcquire(10, 15, TimeUnit.SECONDS); if (res) { try { ... } finally { semaphore.release(); } }RSemaphore semaphore = redisson.getSemaphore("mySemaphore"); // acquire single permit semaphore.acquire(); // or acquire 10 permits semaphore.acquire(10); // or try to acquire permit boolean res = semaphore.tryAcquire(); // or try to acquire permit or wait up to 15 seconds boolean res = semaphore.tryAcquire(15, TimeUnit.SECONDS); // or try to acquire 10 permit boolean res = semaphore.tryAcquire(10); // or try to acquire 10 permits or wait up to 15 seconds boolean 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();RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch"); latch.trySetCount(1); // await for count down latch.await(); // in other thread or JVM RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch"); latch.countDown();RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch"); latch.trySetCount(1); // await for count down latch.await(); // in other thread or JVM RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch"); latch.countDown();
参考
https://blog.csdn.net/weixin_42373241/article/details/139441473
来源链接:https://www.cnblogs.com/cjsblog/p/18641357
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
暂无评论内容