创建线程池

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

目录

线程池定义

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

解决的问题(需求)

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

工作原理

实现线程池创建示意图

重要构造器

创建线程池(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 来创建 线程池对象的。


拓展

思考

任务拒绝策略

参考视频

黑马磊哥


相关推荐
keep one's resolveY12 分钟前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克31 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠2 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌2 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局2 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源2 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it2 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java
消失的旧时光-19433 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
NE_STOP3 小时前
Redis--发布订阅命令和Redis事务
java
PAC_3Dame3 小时前
记一次真实的线上OOM
java