自定义线程池代码+详解

本文深入探讨了线程池的工作原理,包括核心线程、任务队列和饱和策略。通过实例代码,详细解释如何自定义线程池,包括任务类、执行类(Worker)和线程池类的设计,强调了任务队列在执行任务过程中的作用,并展示了如何通过Worker将任务按顺序执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先明白线程池工作原理。
当线程池提交一个任务时,首先会判断核心线程数是否已满,没满就直接new一个核心线程去执行任务。
如果满了,就尝试加到任务队列里。
首先判断任务队列是否满了,没满就直接加,满了就去查看是否可以直接new一个非核心线程去执行任务。
先看线程池内线程数是否已达到最大,如果没达到,那就直接new一个非核心线程去执行任务,如果达到了那就根据饱和策略来拒绝任务。
工作原理就是这样,现在我们来尝试自定义线程,我们需要四样东西。
首先是测试类,没什么可说的。
重点的三样是:
任务类
worker执行类
线程池

任务类负责提交任务。
执行类用来执行任务所以它要掌握全部任务,所以它要有一个任务队列作为成员变量。
线程池,用来提交任务,内部通过worker来接收任务并执行。但这不代表他要有一个成员变量worker。
线程池内部有一个linkedlist来缓存任务并保证任务按顺序执行。当它new一个worker启用时,会把当前任务队列传进去。

上代码,注释很详细。
首先是任务类,实现Runnable接口。

package test5_19;
//自定义线程池的任务类
public class MyTask implements Runnable {
    private int id;
    public MyTask(int id){
        this.id = id;
    }
    public void run(){
        String name = Thread.currentThread().getName();
        System.out.println("线程"+name+"即将运行任务"+id);
        try {
            Thread.sleep(200l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程"+name+"完成了任务"+id);
    }
    public String toString(){
        return "mytask{"+"id="+id+'}';
    }
}

执行类Myworker 内部有缓存任务的队列,取出一个任务并执行

package test5_19;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
//执行类worker,用于执行任务,所以要拥有所有任务
public class MyWorker extends Thread {
    //任务队列
    private List<Runnable> task;
    public MyWorker(String name,List<Runnable> task){
        super(name);
        this.task=task;
    }
    public void run(){
        while (task.size()>0){
            Runnable r = task.remove(0);
            r.run();
        }
    }
}
class MyThreadPool{
    private  List<Runnable> task= Collections.synchronizedList(new LinkedList<>());
    // Collections.synchronized()通过这个方法获得一个安全的linkedlist
    private int num;//任务数量
    private int corePoolSize;//核心线程数目
    private int workSize;//任务队列里最多任务数
    private int maxSize;//最大线程总数
    public MyThreadPool(int corePoolSize,int workSize,int maxSize){
        this.corePoolSize=corePoolSize;
        this.maxSize=maxSize;
        this.workSize=workSize;
    }
    public void submit(Runnable r){
    if(task.size()>=workSize){
        System.out.println("任务"+r+"被丢弃");
    }else {
        task.add(r);
        execTask(r);
    }
    }

    private void execTask(Runnable r){
        if (num<corePoolSize){
            new MyWorker("核心线程"+num,task).start();;
            num++;
        }else if(num<maxSize){
            new MyWorker("非核心线程"+num,task).start();;
            num++;
        }else {
            System.out.println("任务"+r+"被缓存了");
        }
    }
}

线程池,内部通过Worker来执行任务,它负责缓存任务,然后把任务队列提交给worker

class MyThreadPool{
    private  List<Runnable> task= Collections.synchronizedList(new LinkedList<>());
    // Collections.synchronized()通过这个方法获得一个安全的linkedlist
    private int num;//任务数量
    private int corePoolSize;//核心线程数目
    private int workSize;//任务队列里最多任务数
    private int maxSize;//最大线程总数
    public MyThreadPool(int corePoolSize,int workSize,int maxSize){
        this.corePoolSize=corePoolSize;
        this.maxSize=maxSize;
        this.workSize=workSize;
    }
    public void submit(Runnable r){
    if(task.size()>=workSize){
        System.out.println("任务"+r+"被丢弃");
    }else {
        task.add(r);
        execTask(r);
    }
    }

    private void execTask(Runnable r){
        if (num<corePoolSize){
            new MyWorker("核心线程"+num,task).start();;
            num++;
        }else if(num<maxSize){
            new MyWorker("非核心线程"+num,task).start();;
            num++;
        }else {
            System.out.println("任务"+r+"被缓存了");
        }
    }
}

测试类


public class MyTest {
    public static void main(String[] args) {
        MyThreadPool pool=new MyThreadPool(2,3,5);
        for (int i = 0; i < 15; i++) {
            MyTask my = new MyTask(i);
            pool.submit(my);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值