自己动手,写一个简单的线程池(1)

简易线程池实现
本文介绍了一种简易线程池的实现方式,通过任务队列和固定数量的线程来复用线程资源,有效减少频繁创建和销毁线程带来的开销。

在很多场景下,创建线程并执行任务完,我们并不希望线程生命结束。因为重新创建线程的开销很大,如果能复用线程是最好不过得了。所以有了线程池就可以避免重复创建-销毁线程。
现在手写一个简单的线程池

思路
  1. 将执行的任务逻辑抽离,因此需要有一个任务队列
  2. 初始化时创建一定数量的线程,用来执行任务队列中的任务
  3. 当任务队列为空时,线程池中的线程等待唤醒,当有新任务加入时,唤醒线程

按照上述思路,先开始实现

首先定义好任务队列
private static final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>();

并且有一个添加任务的方法

public void addTask(Runnable runnable) {
        synchronized (TASK_QUEUE) {
            TASK_QUEUE.addLast(runnable);
            TASK_QUEUE.notifyAll();
        }
    }

使用同步来保证线程安全,并且在添加完后notifyAll() 来唤醒线程池中的线程。
简单起见,可以将任务队列定义为一个先进先出的队列,因此取任务时,将第一个取出。
定义一个TaskExecutor类,继承Thread,并且重写run方法,作为执行任务的线程。

为了标记被执行任务的状态,使用一个枚举类,分别表示任务的状态
enum TaskState {
        FREE, RUNNING, BLOCKED, DEAD
    }
重新run方法
public void run() {
            OUTER:
            while (taskState != TaskState.DEAD) {
                Runnable runnable;
                synchronized (TASK_QUEUE) {
                    while (TASK_QUEUE.isEmpty()) {
                        try {
                            taskState = TaskState.BLOCKED;
                            TASK_QUEUE.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            break OUTER;
                        }
                    }
                    runnable = TASK_QUEUE.removeFirst();
                }
                taskState = TaskState.RUNNING;
                runnable.run();
                taskState = TaskState.FREE;

            }

        }

如果任务队列为空,则wait,否则获取队列中的Runnable,并执行。使用TASK_QUEUE.removeFirst() 来获取第一个元素,保证先进先出。

完整代码
public class SimpleThreadPool {

    private final int size;
    private final static int DEFAULT_SIZE = 10;
    private static final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>();
    private static final String THREAD_PREFIX = "SIMPLE_THREAD_POOL-";
    private static volatile int seq = 0;
    private static final List<Thread> TASK_EXECUTORS = new ArrayList<>();
    private static final ThreadGroup THREAD_GROUP = new ThreadGroup("Simple_Threadpool_group");

    public SimpleThreadPool() {
        this(DEFAULT_SIZE);
    }

    public SimpleThreadPool(int size) {
        this.size = size;
        init();
    }

    private void init() {
        for (int i = 0; i < size; i++) {
            TaskExecutor taskExecutor = createExecutor();
            TASK_EXECUTORS.add(taskExecutor);
            taskExecutor.start();
        }

    }

    public void addTask(Runnable runnable) {
        synchronized (TASK_QUEUE) {
            TASK_QUEUE.addLast(runnable);
            TASK_QUEUE.notifyAll();
        }
    }

    private TaskExecutor createExecutor() {
        TaskExecutor executor = new TaskExecutor(THREAD_GROUP, THREAD_PREFIX + (seq++));
        return executor;
    }

    enum TaskState {
        FREE, RUNNING, BLOCKED, DEAD
    }

    private class TaskExecutor extends Thread {
        private TaskState taskState = TaskState.FREE;

        private TaskExecutor(ThreadGroup threadGroup, String name) {
            super(threadGroup, name);
        }


        public void run() {
            OUTER:
            while (taskState != TaskState.DEAD) {
                Runnable runnable;
                synchronized (TASK_QUEUE) {
                    while (TASK_QUEUE.isEmpty()) {
                        try {
                            taskState = TaskState.BLOCKED;
                            TASK_QUEUE.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            break OUTER;
                        }
                    }
                    runnable = TASK_QUEUE.removeFirst();
                }
                taskState = TaskState.RUNNING;
                runnable.run();
                taskState = TaskState.FREE;

            }

        }

        public void shutdown() {
            taskState = TaskState.DEAD;
        }
    }

}
测试
public class SimpleThreadPoolTest {
    public static void main(String[] args) {
        SimpleThreadPool pool = new SimpleThreadPool();
        for (int i = 0; i < 40; i++) {
            int finalI = i;
            pool.addTask(() -> {
                System.out.println(Thread.currentThread().getName() + " ==> is execute  task " + finalI);
                try {
                    Thread.sleep(2_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

新建线程池,默认线程10个。给它40个任务

运行结果

SIMPLE_THREAD_POOL-9 ==> is execute  task 0
SIMPLE_THREAD_POOL-1 ==> is execute  task 8
SIMPLE_THREAD_POOL-8 ==> is execute  task 1
SIMPLE_THREAD_POOL-4 ==> is execute  task 5
SIMPLE_THREAD_POOL-5 ==> is execute  task 4
SIMPLE_THREAD_POOL-3 ==> is execute  task 6
SIMPLE_THREAD_POOL-7 ==> is execute  task 2
SIMPLE_THREAD_POOL-6 ==> is execute  task 3
SIMPLE_THREAD_POOL-2 ==> is execute  task 7
SIMPLE_THREAD_POOL-0 ==> is execute  task 9
SIMPLE_THREAD_POOL-1 ==> is execute  task 12
SIMPLE_THREAD_POOL-6 ==> is execute  task 19
SIMPLE_THREAD_POOL-0 ==> is execute  task 18
SIMPLE_THREAD_POOL-2 ==> is execute  task 17
SIMPLE_THREAD_POOL-7 ==> is execute  task 16
SIMPLE_THREAD_POOL-8 ==> is execute  task 11
SIMPLE_THREAD_POOL-9 ==> is execute  task 10
SIMPLE_THREAD_POOL-5 ==> is execute  task 14
SIMPLE_THREAD_POOL-3 ==> is execute  task 15
SIMPLE_THREAD_POOL-4 ==> is execute  task 13
SIMPLE_THREAD_POOL-1 ==> is execute  task 20
SIMPLE_THREAD_POOL-7 ==> is execute  task 26
SIMPLE_THREAD_POOL-0 ==> is execute  task 22
SIMPLE_THREAD_POOL-9 ==> is execute  task 24
SIMPLE_THREAD_POOL-6 ==> is execute  task 21
SIMPLE_THREAD_POOL-8 ==> is execute  task 23
SIMPLE_THREAD_POOL-2 ==> is execute  task 25
SIMPLE_THREAD_POOL-3 ==> is execute  task 27
SIMPLE_THREAD_POOL-4 ==> is execute  task 29
SIMPLE_THREAD_POOL-5 ==> is execute  task 28
SIMPLE_THREAD_POOL-0 ==> is execute  task 30
SIMPLE_THREAD_POOL-6 ==> is execute  task 35
SIMPLE_THREAD_POOL-8 ==> is execute  task 34
SIMPLE_THREAD_POOL-7 ==> is execute  task 31
SIMPLE_THREAD_POOL-9 ==> is execute  task 36
SIMPLE_THREAD_POOL-1 ==> is execute  task 32
SIMPLE_THREAD_POOL-2 ==> is execute  task 33
SIMPLE_THREAD_POOL-3 ==> is execute  task 37
SIMPLE_THREAD_POOL-5 ==> is execute  task 39
SIMPLE_THREAD_POOL-4 ==> is execute  task 38

可以看到40个任务被SIMPLE_THREAD_POOL-0到SIMPLE_THREAD_POOL-9这10个线程执行了,一个简单的线程池就完成了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值