Class ThreadKit

java.lang.Object
org.miaixz.bus.core.xyz.ThreadKit

public class ThreadKit extends Object
线程池工具
Since:
Java 17+
Author:
Kimi Liu
  • Constructor Details

    • ThreadKit

      public ThreadKit()
  • Method Details

    • newExecutor

      public static ExecutorService newExecutor()
      获得一个新的线程池,默认的策略如下:
          1. 初始线程数为 0
          2. 最大线程数为Integer.MAX_VALUE
          3. 使用SynchronousQueue
          4. 任务直接提交给线程而不保持它们
       
      Returns:
      ExecutorService
    • newSingleExecutor

      public static ExecutorService newSingleExecutor()
      获得一个新的线程池,只有单个线程,策略如下:
          1. 初始线程数为 1
          2. 最大线程数为 1
          3. 默认使用LinkedBlockingQueue,默认队列大小为1024
          4. 同时只允许一个线程工作,剩余放入队列等待,等待数超过1024报错
       
      Returns:
      ExecutorService
    • newExecutor

      public static ThreadPoolExecutor newExecutor(int poolSize)
      新建一个线程池,默认的策略如下:
          1. 初始线程数为poolSize指定的大小
          2. 最大线程数为poolSize指定的大小
          3. 默认使用LinkedBlockingQueue,默认无界队列
       
      Parameters:
      poolSize - 同时执行的线程数大小
      Returns:
      ThreadPoolExecutor
    • newExecutor

      public static ThreadPoolExecutor newExecutor(int corePoolSize, int maximumPoolSize)
      获得一个新的线程池 如果maximumPoolSize >= corePoolSize,在没有新任务加入的情况下,多出的线程将最多保留60s
      Parameters:
      corePoolSize - 初始线程池大小
      maximumPoolSize - 最大线程池大小
      Returns:
      ThreadPoolExecutor
    • newExecutor

      public static ExecutorService newExecutor(int corePoolSize, int maximumPoolSize, int maximumQueueSize)
      获得一个新的线程池,并指定最大任务队列大小 如果maximumPoolSize >= corePoolSize,在没有新任务加入的情况下,多出的线程将最多保留60s
      Parameters:
      corePoolSize - 初始线程池大小
      maximumPoolSize - 最大线程池大小
      maximumQueueSize - 最大任务队列大小
      Returns:
      ThreadPoolExecutor
    • newExecutorByBlockingCoefficient

      public static ThreadPoolExecutor newExecutorByBlockingCoefficient(float blockingCoefficient)
      获得一个新的线程池 传入阻塞系数,线程池的大小计算公式为:CPU可用核心数 / (1 - 阻塞因子) Blocking Coefficient(阻塞系数) = 阻塞时间/(阻塞时间+使用CPU的时间) 计算密集型任务的阻塞系数为0,而IO密集型任务的阻塞系数则接近于1。

      see: http://blog.csdn.net/partner4java/article/details/9417663

      Parameters:
      blockingCoefficient - 阻塞系数,阻塞因子介于0~1之间的数,阻塞因子越大,线程池中的线程数越多。
      Returns:
      ThreadPoolExecutor
    • newFixedExecutor

      public static ExecutorService newFixedExecutor(int nThreads, String threadNamePrefix, boolean isBlocked)
      获取一个新的线程池,默认的策略如下
           1. 核心线程数与最大线程数为nThreads指定的大小
           2. 默认使用LinkedBlockingQueue,默认队列大小为1024
           3. 如果isBlocked为true,当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被Thread.interrupt()中断
       
      Parameters:
      nThreads - 线程池大小
      threadNamePrefix - 线程名称前缀
      isBlocked - 是否使用BlockPolicy策略
      Returns:
      ExecutorService
    • newFixedExecutor

      public static ThreadPoolExecutor newFixedExecutor(int nThreads, int maximumQueueSize, String threadNamePrefix, boolean isBlocked)
      获取一个新的线程池,默认的策略如下
           1. 核心线程数与最大线程数为nThreads指定的大小
           2. 默认使用LinkedBlockingQueue
           3. 如果isBlocked为true,当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被Thread.interrupt()中断
       
      Parameters:
      nThreads - 线程池大小
      maximumQueueSize - 队列大小
      threadNamePrefix - 线程名称前缀
      isBlocked - 是否使用BlockPolicy策略
      Returns:
      ThreadPoolExecutor
    • newFixedExecutor

      public static ThreadPoolExecutor newFixedExecutor(int nThreads, int maximumQueueSize, String threadNamePrefix, RejectedExecutionHandler handler)
      获得一个新的线程池,默认策略如下
           1. 核心线程数与最大线程数为nThreads指定的大小
           2. 默认使用LinkedBlockingQueue
       
      Parameters:
      nThreads - 线程池大小
      maximumQueueSize - 队列大小
      threadNamePrefix - 线程名称前缀
      handler - 拒绝策略
      Returns:
      ThreadPoolExecutor
    • execute

      public static void execute(Runnable runnable)
      直接在公共线程池中执行线程
      Parameters:
      runnable - 可运行对象
    • execAsync

      public static Runnable execAsync(Runnable runnable, boolean isDaemon)
      执行异步方法
      Parameters:
      runnable - 需要执行的方法体
      isDaemon - 是否守护线程。守护线程会在主线程结束后自动结束
      Returns:
      执行的方法体
    • execAsync

      public static <T> Future<T> execAsync(Callable<T> task)
      执行有返回值的异步方法 Future代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则,get()会使当前线程阻塞
      Type Parameters:
      T - 回调对象类型
      Parameters:
      task - Callable
      Returns:
      Future
    • execAsync

      public static Future<?> execAsync(Runnable runnable)
      执行有返回值的异步方法 Future代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则,get()会使当前线程阻塞
      Parameters:
      runnable - 可运行对象
      Returns:
      Future
    • newCompletionService

      public static <T> CompletionService<T> newCompletionService()
      新建一个CompletionService,调用其submit方法可以异步执行多个任务,最后调用take方法按照完成的顺序获得其结果。 若未完成,则会阻塞
      Type Parameters:
      T - 回调对象类型
      Returns:
      CompletionService
    • newCompletionService

      public static <T> CompletionService<T> newCompletionService(ExecutorService executor)
      新建一个CompletionService,调用其submit方法可以异步执行多个任务,最后调用take方法按照完成的顺序获得其结果。 若未完成,则会阻塞
      Type Parameters:
      T - 回调对象类型
      Parameters:
      executor - 执行器 ExecutorService
      Returns:
      CompletionService
    • newCountDownLatch

      public static CountDownLatch newCountDownLatch(int taskCount)
      新建一个CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 示例:等6个同学都离开教室,班长才能锁门。
      
       CountDownLatch latch = new CountDownLatch(6); // 总共任务是6
        for (int x = 0; x < 6; x++) {
         //具体生产任务,可以用线程池替换
           new Thread(()->{
               try {
                 //每个同学在教室待上几秒秒钟
                   int time = ThreadLocalRandom.current().nextInt(1, 5);
                   TimeUnit.SECONDS.sleep(time);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.printf("同学【%s】,已经离开了教室%n", Thread.currentThread().getName());
               latch.countDown(); // 减1(每离开一个同学,减去1),必须执行,可以放到 try...finally中
           },"同学 - " + x).start();
       }
       latch.await(); // 等待计数为0后再解除阻塞;(等待所有同学离开)
       System.out.println("【主线程】所有同学都离开了教室,开始锁教室大门了。");
       
       
      该示例,也可以用:Phaser 移相器 进行实现
      Parameters:
      taskCount - 任务数量
      Returns:
      CountDownLatch
    • newCyclicBarrier

      public static CyclicBarrier newCyclicBarrier(int taskCount)
      新建一个CycleBarrier 循环栅栏,一个同步辅助类 示例:7个同学,集齐7个龙珠,7个同学一起召唤神龙;前后集齐了2次
      
               AtomicInteger times = new AtomicInteger();
               CyclicBarrier barrier = new CyclicBarrier(7, ()->{
                   System.out.println("");
                   System.out.println("");
                   System.out.println("【循环栅栏业务处理】7个子线程 都收集了一颗龙珠,七颗龙珠已经收集齐全,开始召唤神龙。" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                   times.getAndIncrement();
               }); // 现在设置的栅栏的数量为2
               for (int x = 0; x < 7; x++) {   // 创建7个线程, 当然也可以使用线程池替换。
                   new Thread(() -> {
                       while (times.get() < 2) {
                           try {
                               System.out.printf("【Barrier - 收集龙珠】当前的线程名称:%s%n", Thread.currentThread().getName());
                               int time = ThreadLocalRandom.current().nextInt(1, 10); // 等待一段时间,模拟线程的执行时间
                               TimeUnit.SECONDS.sleep(time); // 模拟业务延迟,收集龙珠的时间
                               barrier.await(); // 等待,凑够了7个等待的线程
                               System.err.printf("〖Barrier - 举起龙珠召唤神龙〗当前的线程名称:%s\t%s%n", Thread.currentThread().getName(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                               if (barrier.getParties() >= 7) {
                                   barrier.reset(); // 重置栅栏,等待下一次的召唤。
                               }
                           } catch (Exception e) {
                               e.printStackTrace();
                           }
                       }
                   }, "线程 - " + x).start();
               }
       
      该示例,也可以用:Phaser 移相器 进行实现
      Parameters:
      taskCount - 任务数量
      Returns:
      CyclicBarrier
    • newPhaser

      public static Phaser newPhaser(int taskCount)
      新建一个Phaser,一个同步辅助类,jdk1.7提供,可以完全替代CountDownLatch; Pharser: 移相器、相位器,可重用同步屏障; 功能可以替换:CyclicBarrier(固定线程)循环栅栏、CountDownLatch(固定计数)倒数计数、加上分层功能 示例1:等6个同学都离开教室,班长才能锁门。
      
       Phaser phaser = new Phaser(6); // 总共任务是6
        for (int x = 0; x < 6; x++) {
         //具体生产任务,可以用线程池替换
           new Thread(()->{
               try {
                   //每个同学在教室待上几秒秒钟
                 	int time = ThreadLocalRandom.current().nextInt(1, 5);
                   TimeUnit.SECONDS.sleep(5);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.printf("同学【%s】,已经离开了教室%n", Thread.currentThread().getName());
               phaser.arrive(); // 减1 等价于countDown()方法(每离开一个同学,减去1),必须执行,可以放到 try...finally中
           },"同学 - " + x).start();
       }
       phaser.awaitAdvance(phaser.getPhase()); // 等价于latch.await()方法 等待计数为0后再解除阻塞;(等待所有同学离开)
       System.out.println("【主线程】所有同学都离开了教室,开始锁教室大门了。");
       
       
      示例2:7个同学,集齐7个龙珠,7个同学一起召唤神龙; 只需要:phaser.arrive(); --> phaser.arriveAndAwaitAdvance() //等待其他的线程就位 该示例,也可以用:CyclicBarrier 进行实现
      Parameters:
      taskCount - 任务数量
      Returns:
      Phaser
    • newThread

      public static Thread newThread(Runnable runnable, String name)
      创建新线程,非守护线程,正常优先级,线程组与当前线程的线程组一致
      Parameters:
      runnable - Runnable
      name - 线程名
      Returns:
      Thread
    • newThread

      public static Thread newThread(Runnable runnable, String name, boolean isDaemon)
      创建新线程
      Parameters:
      runnable - Runnable
      name - 线程名
      isDaemon - 是否守护线程
      Returns:
      Thread
    • sleep

      public static boolean sleep(Number timeout, TimeUnit timeUnit)
      挂起当前线程
      Parameters:
      timeout - 挂起的时长
      timeUnit - 时长单位
      Returns:
      被中断返回false,否则true
    • sleep

      public static boolean sleep(Number millis)
      挂起当前线程
      Parameters:
      millis - 挂起的毫秒数
      Returns:
      被中断返回false,否则true
    • sleep

      public static boolean sleep(long millis)
      挂起当前线程
      Parameters:
      millis - 挂起的毫秒数
      Returns:
      被中断返回false,否则true
    • safeSleep

      public static boolean safeSleep(Number millis)
      考虑Thread.sleep(long)方法有可能时间不足给定毫秒数,此方法保证sleep时间不小于给定的毫秒数
      Parameters:
      millis - 给定的sleep时间
      Returns:
      被中断返回false,否则true
      See Also:
    • safeSleep

      public static boolean safeSleep(long millis)
      考虑Thread.sleep(long)方法有可能时间不足给定毫秒数,此方法保证sleep时间不小于给定的毫秒数
      Parameters:
      millis - 给定的sleep时间(毫秒)
      Returns:
      被中断返回false,否则true
      See Also:
    • getStackTrace

      public static StackTraceElement[] getStackTrace()
      Returns:
      获得堆栈列表
    • getStackTraceElement

      public static StackTraceElement getStackTraceElement(int i)
      获得堆栈项
      Parameters:
      i - 第几个堆栈项
      Returns:
      堆栈项
    • createThreadLocal

      public static <T> ThreadLocal<T> createThreadLocal(boolean isInheritable)
      创建本地线程对象
      Type Parameters:
      T - 持有对象类型
      Parameters:
      isInheritable - 是否为子线程提供从父线程那里继承的值
      Returns:
      本地线程
    • createThreadLocal

      public static <T> ThreadLocal<T> createThreadLocal(Supplier<? extends T> supplier)
      创建本地线程对象
      Type Parameters:
      T - 持有对象类型
      Parameters:
      supplier - 初始化线程对象函数
      Returns:
      本地线程
      See Also:
    • createThreadFactoryBuilder

      public static ThreadFactoryBuilder createThreadFactoryBuilder()
      创建ThreadFactoryBuilder
      Returns:
      ThreadFactoryBuilder
      See Also:
    • createThreadFactory

      public static ThreadFactory createThreadFactory(String threadNamePrefix)
      创建自定义线程名称前缀的ThreadFactory
      Parameters:
      threadNamePrefix - 线程名称前缀
      Returns:
      ThreadFactory
      See Also:
    • interrupt

      public static void interrupt(Thread thread, boolean isJoin)
      结束线程,调用此方法后,线程将抛出 InterruptedException异常
      Parameters:
      thread - 线程
      isJoin - 是否等待结束
    • waitForDie

      public static void waitForDie()
      等待当前线程结束. 调用 Thread.join() 并忽略 InterruptedException
    • waitForDie

      public static void waitForDie(Thread thread)
      等待线程结束. 调用 Thread.join() 并忽略 InterruptedException
      Parameters:
      thread - 线程
    • getThreads

      public static Thread[] getThreads()
      获取JVM中与当前线程同组的所有线程
      Returns:
      线程对象数组
    • getThreads

      public static Thread[] getThreads(ThreadGroup group)
      获取JVM中与当前线程同组的所有线程 使用数组二次拷贝方式,防止在线程列表获取过程中线程终止
      Parameters:
      group - 线程组
      Returns:
      线程对象数组
    • getMainThread

      public static Thread getMainThread()
      获取进程的主线程
      Returns:
      进程的主线程
    • currentThreadGroup

      public static ThreadGroup currentThreadGroup()
      获取当前线程的线程组
      Returns:
      线程组
    • currentThreadId

      public static long currentThreadId()
      获取当前线程ID,即TID
      Returns:
      TID
    • newNamedThreadFactory

      public static ThreadFactory newNamedThreadFactory(String prefix, boolean isDaemon)
      创建线程工厂
      Parameters:
      prefix - 线程名前缀
      isDaemon - 是否守护线程
      Returns:
      ThreadFactory
    • newNamedThreadFactory

      public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon)
      创建线程工厂
      Parameters:
      prefix - 线程名前缀
      threadGroup - 线程组,可以为null
      isDaemon - 是否守护线程
      Returns:
      ThreadFactory
    • newNamedThreadFactory

      public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon, Thread.UncaughtExceptionHandler handler)
      创建线程工厂
      Parameters:
      prefix - 线程名前缀
      threadGroup - 线程组,可以为null
      isDaemon - 是否守护线程
      handler - 未捕获异常处理
      Returns:
      ThreadFactory
    • sync

      public static void sync(Object obj)
      阻塞当前线程,保证在main方法中执行不被退出
      Parameters:
      obj - 对象所在线程
    • concurrencyTest

      public static ConcurrencyTester concurrencyTest(int threadSize, Runnable runnable)
      并发测试 此方法用于测试多线程下执行某些逻辑的并发性能 调用此方法会导致当前线程阻塞。 结束后可调用ConcurrencyTester.getInterval() 方法获取执行时间
      Parameters:
      threadSize - 并发线程数
      runnable - 执行的逻辑实现
      Returns:
      ConcurrencyTester
    • createScheduledExecutor

      public static ScheduledThreadPoolExecutor createScheduledExecutor(int corePoolSize)
      Parameters:
      corePoolSize - 初始线程池大小
      Returns:
      ScheduledThreadPoolExecutor
    • schedule

      public static ScheduledExecutorService schedule(ScheduledExecutorService executor, Runnable command, long initialDelay, long period, boolean fixedRateOrFixedDelay)
      开始执行一个定时任务,执行方式分fixedRate模式和fixedDelay模式。 注意:此方法的延迟和周期的单位均为毫秒。
      • fixedRate 模式:以固定的频率执行。每period的时刻检查,如果上个任务完成,启动下个任务,否则等待上个任务结束后立即启动。
      • fixedDelay模式:以固定的延时执行。上次任务结束后等待period再执行下个任务。
      Parameters:
      executor - 定时任务线程池,null新建一个默认线程池
      command - 需要定时执行的逻辑
      initialDelay - 初始延迟,单位毫秒
      period - 执行周期,单位毫秒
      fixedRateOrFixedDelay - true表示fixedRate模式,false表示fixedDelay模式
      Returns:
      ScheduledExecutorService
    • schedule

      public static ScheduledExecutorService schedule(ScheduledExecutorService executor, Runnable command, long initialDelay, long period, TimeUnit timeUnit, boolean fixedRateOrFixedDelay)
      开始执行一个定时任务,执行方式分fixedRate模式和fixedDelay模式。
      • fixedRate 模式:以固定的频率执行。每period的时刻检查,如果上个任务完成,启动下个任务,否则等待上个任务结束后立即启动。
      • fixedDelay模式:以固定的延时执行。上次任务结束后等待period再执行下个任务。
      Parameters:
      executor - 定时任务线程池,null新建一个默认线程池
      command - 需要定时执行的逻辑
      initialDelay - 初始延迟
      period - 执行周期
      timeUnit - 时间单位
      fixedRateOrFixedDelay - true表示fixedRate模式,false表示fixedDelay模式
      Returns:
      ScheduledExecutorService