用户国营 发表于 2024-12-31 09:51:54

多线程开发常见题目汇总

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/
https://img2024.cnblogs.com/blog/874963/202412/874963-20241230163828548-198566522.png

<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 
  
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 多线程开发常见题目汇总