6种线程池

线程池:

① 定长

/**
 * 定长线程池5个线程,100个线程要运行,5个满了就进入队列
 * 如果一个线程完了,那么线程放入线程池中不会消失,新的又进来运行了
 */
public class Fixed {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 100; i++) {
            try {
                TimeUnit.MICROSECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            es.execute(()->{
                System.out.println(Thread.currentThread().getName());
            });
        }
        // 关闭线程池
        es.shutdown();
    }
}
//        es.shutdownNow(); // 直接关闭
//        es.isTerminated();// 是否都执行完
//        es.isShutdown();  // 是否关闭了,并不代表执行完

② 缓存弹性

/**
 * 缓存:刚开始一个线程都没有,来一个任务起一个线程
 * 此时来第二个线程,若第一个空闲则占用,第一个在运
 * 行则新创建。最大是Integer.MAX_VALUE
 * 默认的话,一个线程空闲超过一分钟,线程销毁。
 */
public class Cached {
    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            es.execute(()->{
                System.out.println(Thread.currentThread().getName());
            });
        }
        es.shutdown();
    }
}

单例

/**
 * 单例
 * 核心线程:1
 * 最大线程:1
 * 保证执行顺序
 */
public class Single {
    public static void main(String[] args) {
        ExecutorService es = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 100; i++) {
            es.execute(()->{
                System.out.println(Thread.currentThread().getName());
            });
        }
    }
}

④ 定时

/**
 * 定时执行,自己设定核心线程数
 */
public class Schedule {
    public static void main(String[] args) {
        ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
            ses.scheduleAtFixedRate(()->{
                System.out.println(Thread.currentThread().getName());
            },0,500, TimeUnit.MICROSECONDS); // 第一个0秒后开始,之后经过多久执行
    }
}

⑤ 精灵线程

// 本质上和ForkJoinPool是同一个线程池
// 维护的池任务列比较长,执行完直接结束不合适,精灵线程自己去拿
public class WorkStealing {
    public static void main(String[] args) throws IOException {
        ExecutorService es = Executors.newWorkStealingPool();
        // 查看CPU几核  4 , WorkStealingPool默认起4个线程
        System.out.println(Runtime.getRuntime().availableProcessors());
        es.execute(new R(1000));  // 进入等待,哪个空了就自己来拿
        es.execute(new R(2000));
        es.execute(new R(2000));
        es.execute(new R(2000));
        es.execute(new R(2000));  // 第五个等着,第五个任务一定是第一个线程去运行
        // 精灵线程是daemon线程,主函数main一旦结束,后台可能还在运行,但是看不到输出
        // 由于产生的是精灵线程(守护线程、后台线程),主线程不阻塞的话看不到输出
        System.in.read();
    }
    static class R implements Runnable{
        int time;   // 睡多久,打印当前线程名称
        R(int t){
            this.time = t;
        }
        @Override
        public void run() {
            try {
                TimeUnit.MICROSECONDS.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(time+""+Thread.currentThread().getName());
        }
    }
}

⑥ ForkJoin

public class ForkJoin {
    // 100万个数做一个总和
    static int[] nums = new int[1000000];
    static final int MAX_NUM = 50000; // 每一个小任务最多不超过5万个
    static Random r = new Random();
    // 方式一
    static {
        for (int i = 0; i < nums.length; i++) {
            nums[i] = r.nextInt(100);
        }
        System.out.println(Arrays.stream(nums).sum()); // Java8中的String api
    }

//    // 方式二,使用ForkJoin递归,没有返回值,没计算结果
//    static class AddTask extends RecursiveAction{
//
//        int start,end;
//        AddTask(int start,int end){
//            this.start = start;
//            this.end = end;
//        }
//        @Override
//        protected void compute() {
//            // 如果在50000个以内
//            if((end - start) <= MAX_NUM){
//                long sum = 0L;
//                for (int i = start; i < end; i++) sum += nums[i];
//                System.out.println("from:"+start+"to:"+end+"="+sum);
//            }else {
//                // 如果大于50000个,二分法拆分,递归
//                int middle = start + (end - start)/2;
//                AddTask task1 = new AddTask(start, middle);
//                AddTask task2 = new AddTask(middle, end);
//                task1.fork(); // task1全部递归完换task2
//                task2.fork();
//            }
//        }
//    }
    // 使用RecursiveTask,返回值,泛型
    static class AddTask extends RecursiveTask<Long>{
        int start, end;
        AddTask(int start, int end) {
        this.start = start;
        this.end = end;
        }
        @Override
        protected Long compute() {
            if(end - start <= MAX_NUM){
                long sum = 0L;
                for (int i = start; i < end; i++) sum += nums[i];
                return sum;
            }else {
                // 如果大于50000个,二分法拆分,递归
                int middle = start + (end - start)/2;
                AddTask task1 = new AddTask(start, middle);
                AddTask task2 = new AddTask(middle, end);
                task1.fork();
                task2.fork();
                return task1.join() + task2.join();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        ForkJoinPool fjp = new ForkJoinPool();
        AddTask task = new AddTask(0, nums.length);
        fjp.execute(task);
        Long result = task.join();
        System.out.println(result);
//        System.in.read();
    }
}

 

Executor 提供了多种类型的线程池,以满足不同场景下的任务执行需求。这些线程池通过 `Executors` 类的工厂方法创建,每种线池具有不同的行为和适用场景: ### 1. **FixedThreadPool** 创建一个固定大小的线程池,该线程池中的线程数量始终保持不变。当有多个任务需要并发执行时,线程池会复用已有的线程,避免频繁创建和销毁线程带来的开销。适用于负载较重、任务量稳定的系统环境[^4]。 ```java ExecutorService executor = Executors.newFixedThreadPool(5); ``` ### 2. **CachedThreadPool** 创建一个可根据需要创建新线程线程池,但在以前构造的线程可用时将重用它们。适用于执行大量短期异步任务的场景,空闲线程在超时后会被回收,避免资源浪费。线程池的最大线程数为 `Integer.MAX_VALUE`,因此理论上可以容纳无限数量的任务[^2]。 ```java ExecutorService executor = Executors.newCachedThreadPool(); ``` ### 3. **SingleThreadExecutor** 创建一个单线程线程池,该线程池保证所有任务按照提交顺序依次执行。适用于需要保证任务顺序执行的场景,并且具备线程复用的能力。即使任务执行过程中线程发生异常终止,线程池也会创建一个新的线程来替代。 ```java ExecutorService executor = Executors.newSingleThreadExecutor(); ``` ### 4. **ScheduledThreadPool** 创建一个支持定时和周期性任务执行的线程池,适用于需要延迟执行或定期执行任务的场景。该线程池提供了 `schedule`、`scheduleAtFixedRate` 和 `scheduleWithFixedDelay` 等方法来控制任务的执行时机。 ```java ScheduledExecutorService executor = Executors.newScheduledThreadPool(3); executor.schedule(() -> System.out.println("Task executed after 5 seconds"), 5, TimeUnit.SECONDS); ``` ### 5. **WorkStealingPool(Java 8+)** 使用 ForkJoinPool 实现的线程池,支持工作窃取机制,可以更高效地利用多核处理器资源。适用于并行计算任务,尤其适合任务数量较多且执行时间差异较大的场景。 ```java ExecutorService executor = Executors.newWorkStealingPool(); ``` ### 6. **SingleThreadScheduledExecutor** 与 `ScheduledThreadPool` 类似,但只使用一个线程执行定时任务。适用于需要按顺序执行的定时任务或周期性任务,确保任务之间的执行顺序。 ```java ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); executor.scheduleAtFixedRate(() -> System.out.println("Executing every 2 seconds"), 0, 2, TimeUnit.SECONDS); ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值