文件链接:

提取码:xyem

自定义线程池 - 实现步骤

java 自定义线程池需要关闭么 自定义一个线程池_线程池

1、先创建一个任务类 - MyTask

代码示例:

package com.zhoulz.demo01;

/**
 * 需求:
 *     自定义线程池练习,这是任务类,需要实现Runnable接口;
 *     包含任务编号,每一个任务执行时间设计为0.2秒
 */
public class MyTask implements Runnable{
    // 手动的加上一个任务编号
    private int id;
    // 由于run()方法是重写的方法,所以不能加参数(比如加id),怎么办?
    // : id这个属性初始化可以利用构造方法完成

    public MyTask(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println("线程:"+name+"即将执行任务:"+id);
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程:"+name+"完成了任务:"+id);
    }

    @Override
    public String toString() {
        return "MyTask{" +
                "id=" + id +
                '}';
    }
}

2、接着,创建一个线程类 - MyWorker

代码示例:

package com.zhoulz.demo01;

import java.util.List;

/**
 *  需求:
 *      编写一个线程类,需要继承Thread类,设计一个属性,用于保存现成的名字;
 *      设计一个集合,用于保存所有的任务,后面用于执行。
 */
public class MyWorker extends Thread{
    private String name; // 保存线程的名字
    private List<Runnable> tasks;

    // 利用构造方法,给成员变量赋值
    public MyWorker(String name, List<Runnable> tasks) {
        super(name);
        this.tasks = tasks;
    }

    @Override
    public void run() {
        // 判断集合中是否有任务,只要有,就一直执行
        while (tasks.size() > 0){
            // 把第一个任务移除出来
            Runnable r = tasks.remove(0);
            // 然后去执行这个任务
            r.run();
        }
    }
}

3、然后,创建一个线程池类 - MyThreadPool

代码示例:

package com.zhoulz.demo01;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * 这是自定义的线程池类;
 *
 * 成员变量:
 *          1.任务队列 - 集合  (需要控制线程安全问题)
 *          2.当前线程数量
 *          3.核心线程数量
 *          4.最大线程数量
 *          5.任务队列的长度
 * 成员方法:
 *          1.提交任务:
 *                      将任务添加到集合中,需要判断是否超出了任务队列的总长度
 *          2.执行任务:
 *                      判断当前线程的数量,决定创建核心线程还是非核心线程
 */
public class MyThreadPool {
    // 1.任务队列 - 集合  (需要控制线程安全问题)
    //private List<Runnable> tasks = new LinkedList<>(); // LinkedList 不能保证线程的安全
    private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
    // 2.当前线程数量
    private int num;
    // 3.核心线程数量
    private int corePoolSize;
    // 4.最大线程数量
    private int maxSize;
    // 5.任务队列的长度
    private int workSize;

    // 需要带参的构造方法 —— 带后面3个参数即可
    public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
        this.corePoolSize = corePoolSize;
        this.maxSize = maxSize;
        this.workSize = workSize;
    }

    // 1.提交任务:(并执行任务,执行任务的方法另行创建了)
    public void submit(Runnable r){
        // 判断当前集合中任务的数量,是否超出了最大任务数量
        if (tasks.size() >= workSize){
            System.out.println("任务:"+ r + "被丢弃了。。。");
        }else {
            tasks.add(r);
            // 然后执行任务
            execTask(r);
        }
    }

    // 2.执行任务:
    private void execTask(Runnable r) {
        // 判断当前线程池中的线程总数量,是否超越了核心线程数量:
                            // 如果没超出,则直接创建一个新的线程来处理任务;
                            // 如果超出了,则还要进一步判断是否超出了最大线程数量:
                                            // 如果没有超出最大线程数量,则要去创建非核心线程
                                            // 如果超出最大线程数量,则要使其处于等待状态,即在任务缓存队列缓存一会
        if (num < corePoolSize){
            // 如果小于,则直接去创建线程
            new MyWorker("核心线程:"+ num,tasks).start();
            num ++;
        }else if (num < maxSize){
            new MyWorker("非核心线程:"+num,tasks).start();
            num ++;
        }else {
            System.out.println("任务:"+ r + "被缓存了。。。");
        }
    }
}

4、最后,创建测试类 - MyTest

代码示例:

package com.zhoulz.demo01;

/**
 * 测试类:
 *        1、创建线程池类对象;
 *        2、提交多个任务 —— 采用循环的方式
 */
public class MyTest {
    public static void main(String[] args) {
        // 1、创建线程池类对象;
        MyThreadPool pool = new MyThreadPool(2,4,20);

        // 2、提交多个任务 —— 采用循环的方式
        for (int i = 0; i < 10; i++) {
            // 3、创建任务对象,并提交给线程池
            MyTask myTask = new MyTask(i);
            pool.submit(myTask);
        }
    }
}

运行结果:

java 自定义线程池需要关闭么 自定义一个线程池_线程池_02

可以在测试类中改变提交的任务数,运行以作比较。