首页 > 其他分享 >多线程开发常见问题汇总

多线程开发常见问题汇总

时间:2024-12-31 09:52:28浏览次数:1  
标签:常见问题 Thread latch 汇总 线程 semaphore new 多线程 public

1. Thread.UncaughtExceptionHandler

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

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

@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() {
        @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 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 down
latch.await();

// in other thread or JVM
RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch");
latch.countDown();

 

参考

https://blog.csdn.net/weixin_42373241/article/details/139441473 

  

 

标签:常见问题,Thread,latch,汇总,线程,semaphore,new,多线程,public
From: https://www.cnblogs.com/cjsblog/p/18641357

相关文章

  • 《Java核心技术 I》容易忽视和重要的知识点汇总
    本文对《Java核心技术I》中开发者容易忽视和重要的知识点进行总结,不包含一般开发者都知道内容。大标题后括号的数字代表书中对应的章节。一、Java的基本程序设计结构(3)1.整数表示可以为数字字面量加上下划线,这些下划线只是为了让人更易读。Java编译器会去除这些下划线。intn......
  • 【汇总】Android 常用知识连接
    前言全局说明一、说明1.1环境:二、链接2.1代号、标记和build号https://source.android.com/docs/setup/reference/build-numbers?hl=zh-cn#source-code-tags-and-buildshttps://source.android.com/docs/setup/about/build-numbers?hl=zh-cn#buildhttps://xmanyou.c......
  • 【汇总】Android 版本号、版本名称、api版本、内核版本、发布日期
    一、说明网上有大佬,将相关内容整理了,但是每个版本都有一些没有信息,需要来回切换页面查看,所以将所有信息合并。方便查看。 二、表格 Android版本APILevelLinux内核版本代号首次发布日期后续Android版本支持截止日期Android1636 W   Android15356......
  • JavaScript开发中常见问题代码和相关优化Demo参考5.0
    41. 过度使用全局状态管理问题代码:在小型项目中引入了复杂的全局状态管理库(如Redux),增加了不必要的复杂性。解决方案:对于小型应用或简单状态管理需求,考虑使用React的useState和useContext,或者Vuex等框架自带的状态管理功能。//使用ReactContextAPIconstThemeContext=......
  • DataGrip 2024.3安装详细教程与激活方法(附常见问题解决)
    DataGrip概述DataGrip是一款功能强大的,适用于关系数据库和NoSQL数据库的强大跨平台工具温馨提示:本文中的方法仅供学习交流使用,如果条件允许,请支持正版软件。删除旧版本DataGrip如果您的电脑中已经安装了旧版本的DataGrip,建议首先将其完全卸载。操作步骤如下(如果未安装......
  • Apache Hive常见问题
    入门问题什么是ApacheHive?解释Hive的用途。Hive作为基于Hadoop的数据仓库工具是如何工作的?与传统关系型数据库相比,使用Hive有什么优势?Hive和关系型数据库管理系统(RDBMS)之间的区别是什么?讨论诸如数据存储、模式灵活性和性能等关键区别。解释Hive的架构。Hive架构的主......
  • Java多线程实战避坑指南:从入门到生产实践
    在微服务架构下,多线程编程已经成为Java开发者的必备技能。本文将帮助你掌握多线程开发的核心知识,避开常见陷阱。一、为什么要深入理解多线程?1.1现实问题接口响应慢CPU利用率低内存泄漏频发死锁难以排查并发BUG难复现1.2业务场景批量数据处理并行任务执行......
  • POSIX 多线程 ------ 线程
    多线程当引入线程后,进程可以看作是资源的集合,线程可以看作是执行单元,线程之间共享进程的某些资源,比如文件描述符等等,这方便了线程之间的通信,每个线程都有自己的堆栈(因为线程的启动函数可能不同,甚至可能递归)简单来说就是,同一个进程内的线程可以共享一些资源,每个线程都有自己的......
  • 选题指南:计算机视觉毕业设计选题题目汇总 创新思路
    目录前言毕设选题开题指导建议更多精选选题选题帮助最后前言大家好,这里是海浪学长毕设专题!大四是整个大学期间最忙碌的时光,一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整理了计算机专业最新......
  • 【C语言】多进程/多线程
    多进程/多线程多进程服务器步骤代码多线程一、线程创建和回收二、线程属性三、线程分离多进程服务器步骤  服务器使用父进程fork创建子进程来和客户端进行通信,父进程负责取出连接请求。并且父进程接收子进程退出信号,通过信号处理函数回收子进程步骤:1.首先屏......