创建线程池

如何创建线程池及处理相应任务

目录

线程池定义

注:线程池 就是一个可以复用线程 的技术,控制线程和任务的数量 ;线程池中线程长久存在

解决的问题(需求)

用户每发起一个请求 ,后台就需要 创建一个新线程来处理 ,下次新任务 来了肯定又要创建 新线程处理的,而创建 新线程的开销是很大的 ,并且请求过多时 ,肯定会产生大量的线程出来,这样会严重影响系统的性能 ,甚至可能会引起系统瘫痪(宕机)

工作原理

实现线程池创建示意图

重要构造器

创建线程池(ExecutorService)

注:通过实现类ThreadPoolExecutor()来创建。

java 复制代码
package com.xie.thread.pool.demo;

import java.util.concurrent.*;

/**
 * 掌握线程池的创建 通过有参构造器创建
 * */
public class ThreadPoolTest {
    public static void main(String[] args) {
        /**
         * 创建线程池,其各参数具体含义:
         * 参数一:核心线程数量
         * 参数二:最大线程数量
         * 参数三:临时线程存活时间
         * 参数四:参数三的时间单位
         * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
         * 参数六:线程工厂,用于创建核心线程的
         * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
         * */
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

线程池任务处理


常用API

注:上面为处理处理Runnable任务的API


注:上面为处理处理Callable任务的API


处理Runnable任务

Runnable任务类

java 复制代码
package com.xie.thread.pool.task1.pojo;

/**
 * Runnable任务类,线程的任务对象模版
 * */
public class MyRunnable implements Runnable {
    /**
     * 执行任务区域(即run方法),描述所要执行的任务
     */
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "==> 输出666~~");
        /** 延迟,模拟业务执行耗时,为了便于观察 */
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试

java 复制代码
package com.xie.thread.pool.task1;

import com.xie.thread.pool.task1.pojo.MyRunnable;
import java.util.concurrent.*;
/**
 * 处理Runnable任务
 * */
public class ThreadPoolTest {
    public static void main(String[] args) {
        /**
         * 创建线程池,其各参数具体含义:
         * 参数一:核心线程数量
         * 参数二:最大线程数量
         * 参数三:临时线程存活时间
         * 参数四:参数三的时间单位
         * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
         * 参数六:线程工厂,用于创建核心线程的
         * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
         * 注:线程池可以一直存活,除非主动去关闭
         * */
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        // 创建任务对象
        Runnable taskObject = new MyRunnable();
        // 把任务对象 交给 线程池执行。 注:线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
        pool.execute(taskObject);
        pool.execute(taskObject);
        pool.execute(taskObject);
        pool.execute(taskObject);
        pool.execute(taskObject);
        pool.execute(taskObject);
        pool.execute(taskObject);
        // 创建临时线程时机
        pool.execute(taskObject);
        pool.execute(taskObject); /** 对于此线程池来说,此第九个任务为极限值 */
        // 拒绝策略生效时机( 任务数量 > (5 + 4) )
        // pool.execute(taskObject);
        /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
        pool.shutdown();
        // 立即关闭线程池! 不管任务是否执行完毕!
        // pool.shutdownNow();
    }
}

处理Callable任务

Callable任务类

java 复制代码
package com.xie.thread.pool.task2.pojo;

import java.util.concurrent.Callable;
/**
 * 让这个类实现callable接口  Callable任务类
 * */
public class MyCallable implements Callable<String> {
    private int n;
    public MyCallable(int n) {
        this.n = n;
    }

    /** 重写call方法 此为线程池后期调用的 任务方法(call方法) */
    @Override
    public String call() throws Exception {
        // 描述线程要执行的任务,返回线程执行完后的返回结果
        int sum = 0;
        for (int i = 0; i <= n; i++) {
            sum += i;
        }
        return Thread.currentThread().getName() + " 求出了 1-" + n + " 的和是:" + sum;
    }
}

测试

java 复制代码
package com.xie.thread.pool.task2;

import com.xie.thread.pool.task2.pojo.MyCallable;
import java.util.concurrent.*;
/**
 * 处理Callable任务
 * Callable任务的最大特点:线程池处理任务完后,可以直接获取处理完任务后的结果
 * */
public class ThreadPoolTest {
    public static void main(String[] args) throws Exception {
        /**
         * 创建线程池,其各参数具体含义:
         * 参数一:核心线程数量
         * 参数二:最大线程数量
         * 参数三:临时线程存活时间
         * 参数四:参数三的时间单位
         * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
         * 参数六:线程工厂,用于创建核心线程的
         * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
         * 注:线程池可以一直存活,除非主动去关闭
         * */
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        /** 使用已定义的有参构造器,创建任务对象 Callable对象 并交给线程池 处理
         *  并返回一个未来任务对象
         *  */
        Future<String> futureTask1 = pool.submit(new MyCallable(100));
        Future<String> futureTask2 = pool.submit(new MyCallable(200));
        Future<String> futureTask3 = pool.submit(new MyCallable(300));
        Future<String> futureTask4 = pool.submit(new MyCallable(400));
        Future<String> futureTask5 = pool.submit(new MyCallable(500));
        // 获取执行结果 并打印输出
        System.out.println(futureTask1.get());
        System.out.println(futureTask2.get());
        System.out.println(futureTask3.get());
        System.out.println(futureTask4.get());
        System.out.println(futureTask5.get());
        /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
        pool.shutdown();
        /** 测试 */
        // Callable my = new MyCallable(100);
        // System.out.println(my.call());
    }
}

使用工具类(Executors)创建线程池

常用API

应用案例

测试

java 复制代码
package com.xie.thread.pool.tool;

import com.xie.thread.pool.task2.pojo.MyCallable;
import java.util.concurrent.*;
/**
 * --->通过工具类Executors创建线程池对象
 * Executors是一个线程池的工具类,提供了很多静态方法用于返回不同特点的线程池对象
 *
 * final关键字(修饰符)作用:
 * 不能被继承,不能被修改???
 *
 * 注:此工具类中这些静态方法的底层,都是通过 线程池的实现类ThreadPoolExecutor 创建 的线程池对象。
 * 使用风险:
 * 大型并发系统环境中使用Executors如果不注意可能会出现系统风险
 * 所以,建议推荐使用 ThreadPoolExecutor()类 来创建线程池。
 *
 * 拓展知识:
 * 核心线程数量配置的参考策略:
 * 1,计算密集型的任务:核心线程数量 = CPU的核数 + 1
 * 2,IO密集型的任务:核心线程数量 = CPU核数 * 2
 * */
public class ThreadPoolTest {
    public static void main(String[] args) throws Exception {

        /** 通过工具类Executors方式 创建 线程池对象 新建固定线程数量的线程池(此处定义为3个) */
        final ExecutorService pool = Executors.newFixedThreadPool(3);
        /** 使用已定义的有参构造器,创建任务对象 Callable对象 并交给线程池 处理
         *  并返回一个未来任务对象
         *  */
        Future<String> futureTask1 = pool.submit(new MyCallable(100));
        Future<String> futureTask2 = pool.submit(new MyCallable(200));
        Future<String> futureTask3 = pool.submit(new MyCallable(300));
        Future<String> futureTask4 = pool.submit(new MyCallable(400));
        Future<String> futureTask5 = pool.submit(new MyCallable(500));
        // 获取执行结果 并打印输出
        System.out.println(futureTask1.get());
        System.out.println(futureTask2.get());
        System.out.println(futureTask3.get());
        System.out.println(futureTask4.get());
        System.out.println(futureTask5.get());
        /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
        pool.shutdown();
    }
}

注:此工具类中的这些静态方法的底层都是通过 线程池的 实现类ThreadPoolExecutor 来创建 线程池对象的。


拓展

思考

任务拒绝策略

参考视频

黑马磊哥


相关推荐
HalvmånEver3 小时前
7.高并发内存池大页内存申请释放以及使用定长内存池脱离new
java·spring boot·spring
凤山老林3 小时前
SpringBoot 使用 H2 文本数据库构建轻量级应用
java·数据库·spring boot·后端
赶路人儿4 小时前
UTC时间和时间戳介绍
java·开发语言
dreamread4 小时前
【SpringBoot整合系列】SpringBoot3.x整合Swagger
java·spring boot·后端
6+h4 小时前
【java】基本数据类型与包装类:拆箱装箱机制
java·开发语言·python
一直都在5725 小时前
Spring面经
java·后端·spring
xiaoye37085 小时前
如何在Spring中使用注解配置Bean的生命周期回调方法?
java·spring
闻哥5 小时前
深入Redis的RDB和AOF两种持久化方式以及AOF重写机制的分析
java·数据库·spring boot·redis·spring·缓存·面试
jgyzl5 小时前
2026.3.12 常见的缓存读写策略
java·后端·spring
ruanyongjing5 小时前
Spring TransactionTemplate 深入解析与高级用法
java·数据库·spring