创建线程池

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

目录

线程池定义

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

解决的问题(需求)

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

工作原理

实现线程池创建示意图

重要构造器

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


拓展

思考

任务拒绝策略

参考视频

黑马磊哥


相关推荐
梦想不只是梦与想4 分钟前
鸿蒙系统开发状态更新字段区别对比
android·java·flutter·web·鸿蒙
PHASELESS41138 分钟前
Java堆结构深度解析:原理、实现与应用全指南
java·开发语言·数据结构
DreamBoat_Onism38 分钟前
JVM 内存调优
java·jvm·后端
顺天gie44 分钟前
idea中提高编译速度研究
java·spring boot·intellij-idea
异常君1 小时前
深入 JVM:线程池源码剖析与性能调优全攻略
java·jvm·后端
Light___mmm1 小时前
注入Java Bean的方式
java
xcLeigh1 小时前
HTML5好看的水果蔬菜在线商城网站源码系列模板4
java·前端·源码·html5
烟沙九洲2 小时前
算法的时间复杂度
java·算法
写bug写bug2 小时前
小小 Stream,一篇文章拿捏它
java·后端
写bug写bug2 小时前
好用的Lombok注解
java·后端