关于java:java多线程编程之线程池

3次阅读

共计 3145 个字符,预计需要花费 8 分钟才能阅读完成。

一、什么是线程池(What)?

  • 首先,咱们要了解什么是多线程。一条线程指的是过程中一个繁多程序的控制流,一个过程中能够并发多个线程,每条线程并行执行不同的工作。

< 多线程 > 翻译成人话:相似大家进超市门,很多人挤一个入口通道,太慢了。那就多开明几个入口通道,短时间内解决更多人流量。

  • 而后,再来了解什么是线程池。能够了解成,当时创立好一堆线程,供多任务来应用这些线程,用完后偿还到池内,在设置的某时间段内不销毁,以备其余工作应用。

二、为什么要应用线程池(Why)?

咱们应用线程的时候就去创立一个线程,这样实现起来十分简便,然而就会有一个问题:

如果并发的线程数量很多,并且每个线程都是执行一个工夫很短的工作就完结了,这样频繁创立线程就会大大降低零碎的效率,因为频繁创立线程和销毁线程须要工夫的。

那么有没有一种方法使得线程能够复用,就是执行完一个工作,并不被销毁,而是能够继续执行其余的工作?这就是线程池的诞生起因。

三、怎么应用线程池(How)?

多线程的应用很重要,java 内置包里必定就有解决方案。

线程池执行器:

java.util.concurrent.ThreadPoolExecutor

这里咱们对这个执行器进行简略的设置,写成工具类,便于多处调用。代码如下:

1. 线程池执行器 - 工具类

import java.util.concurrent.*;

/**
 * @author dayaocool
 * @version 1.0
 * @date 2020/08/12 14:27
 */
public class ThreadPoolUtil {
    // 定义一些配置常量,也能够读取内部配置文件

    // 初始化开启的线程数,(可更改查看不同)private static final int corePoolSize = 2;
    // 最大线程数量,不能比 开启的线程数(corePoolSize)小。private static final int maximumPoolSize = 8;
    // 工作队列容量,不能比 最大线程数量(maximumPoolSize)小,// 否则 会触发 队满回绝策略(MyRejectHandler)private static final BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(8);
    // 线程存活工夫 (超过该工夫无任何应用才回销毁线程)
    private static final long keepAliveTime = 2;
    // 线程存活工夫的单位,秒
    private static final TimeUnit unit = TimeUnit.SECONDS;
    // 线程池工厂的 实现类
    private static final ThreadFactory threadFactory = new MyThreadPoolFactory();
    // 工作队列满载回绝处理程序 实现类
    private static final RejectedExecutionHandler rejectedExecutionHandler = new MyRejectHandler();

    /**
     * 线程池工厂的 实现类(外部类)*/
    private static class MyThreadPoolFactory implements ThreadFactory {

        @Override
        public Thread newThread(Runnable r) {Thread thread = new Thread(r, "新线程 -");
            System.out.println(thread.getName() + "创立实现");
            return thread;
        }
    }

    /**
     * 工作队列满载回绝处理程序 实现类(外部类)*/
    private static class MyRejectHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

            // ... 回绝解决的代码可扩大...

            System.out.println(r.toString() + "已被回绝");
        }
    }

    /**
     * 获取 线程池执行器
     * @return 线程池执行器
     */
    public static ThreadPoolExecutor getExecutor() {
        return new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                rejectedExecutionHandler
        );
    }
}

2. 模仿线程工作类

/**
 * @author dayaocool
 * @version 1.0
 * @date 2020/8/12 14:33
 */
public class MyTask implements Runnable {
    private String name;

    public MyTask(String name) {this.name = name;}

    @Override
    public void run() {
        try {
            // 模拟程序 3 秒耗时
            Thread.sleep(3000);

            System.out.println(this.toString() + "运行完结了!");
        } catch (Exception e) {e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return "大尧啊,您的 MyTask{" +
                "name='" + name + '\'' +
                '}';
    }
}

3. 运行调用

/**
 * @author dayaocool
 * @version 1.0
 * @date 2020/8/12 14:48
 */
public class RunTest {public static void main(String[] args) {
        // 模仿 5 个 工作
        MyTask myTask1 = new MyTask("工作 1");
        MyTask myTask2 = new MyTask("工作 2");
        MyTask myTask3 = new MyTask("工作 3");
        MyTask myTask4 = new MyTask("工作 4");
        MyTask myTask5 = new MyTask("工作 5");

        // 从线程池工具类 获取到 线程执行器
        ThreadPoolExecutor executor = ThreadPoolUtil.getExecutor();

        // 并发多线程 执行工作
        executor.execute(myTask1);
        executor.execute(myTask2);
        executor.execute(myTask3);
        executor.execute(myTask4);
        executor.execute(myTask5);
    }
}

输入

  • 先输入 初始化开启的线程数,corePoolSize=2,即开了 2 个线程

新线程 - 创立实现
新线程 - 创立实现

  • 持续输入 (工作先后问题这是 cpu 资源抢占机会的问题)

大尧啊,您的 MyTask{name=’ 工作 2 ′} 运行完结了!
大尧啊,您的 MyTask{name=’ 工作 1 ′} 运行完结了!

  • 持续输入

大尧啊,您的 MyTask{name=’ 工作 3 ′} 运行完结了!
大尧啊,您的 MyTask{name=’ 工作 4 ′} 运行完结了!

  • 最初输入

大尧啊,您的 MyTask{name=’ 工作 5 ′} 运行完结了!

5 个工作,分 2 个并发,执行实现。

总结

线程池主动治理多线程的资源开销,让多线程编程更高效,解决多任务并行迟缓的问题。spring boot 2 框架对线程池的应用更简略,举荐。

转载 请注明出处 思否 - 是大尧啊 https://segmentfault.com/u/dayaocool


正文完
 0