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

来源:互联网 发布:天气软件找不到列治文 编辑:程序博客网 时间:2024/05/17 09:27

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

思路

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

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

阅读全文
0 0
原创粉丝点击