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

来源:互联网 发布:jquery 1.11.0.min.js 编辑:程序博客网 时间:2024/05/21 19:23

上一篇中简单实现了一个线程池,但是还有问题没有解决
1.没有任务加入策略。即可以无限多向任务队列中添加任务
2.没有关闭线程池
因此对其进行改造

任务加入策略

首先定义策略接口及异常

@FunctionalInterfacepublic interface DiscardPolicy {    void discard() throws DiscardException;}
public class DiscardException extends Exception {    public DiscardException(String message) {        super(message);    }}

SimpleThreadPool 中定义任务队列的大小
private static final int TASK_QUEUE_DEFAULT_SIZE = 20;
和策略
private final DiscardPolicy discardPolicy;
修改构造方法

public SimpleThreadPool() {        this(DEFAULT_SIZE, TASK_QUEUE_DEFAULT_SIZE, DEFAULT_POLICY);    }    public SimpleThreadPool(int size, int taskSize, DiscardPolicy discardPolicy) {        this.size = size;        this.TASK_SIZE = taskSize;        this.discardPolicy = discardPolicy;        init();    }

加入任务时做校验

public void addTask(Runnable runnable) throws Exception {        synchronized (TASK_QUEUE) {            }            if (TASK_QUEUE.size() >= TASK_SIZE) {                discardPolicy.discard();            }            TASK_QUEUE.addLast(runnable);            TASK_QUEUE.notifyAll();        }    }

如果大小超过限制,则由策略处理。
这里设置一个默认的策略,即抛出异常

public static final DiscardPolicy DEFAULT_POLICY = () -> {        throw new DiscardException("task size too large.");    };

测试

public class SimpleThreadPoolTest {    public static void main(String[] args) throws Exception {        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();                }            });        }    }}

抛出异常

Exception in thread "main" com.ran.learn.lession2.DiscardException: task size too large.    at com.ran.learn.lession2.SimpleThreadPool.lambda$static$0(SimpleThreadPool.java:25)    at com.ran.learn.lession2.SimpleThreadPool.addTask(SimpleThreadPool.java:56)    at com.ran.learn.lession2.SimpleThreadPoolTest.main(SimpleThreadPoolTest.java:11)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:498)    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)SIMPLE_THREAD_POOL-9 ==> is execute  task 0SIMPLE_THREAD_POOL-3 ==> is execute  task 6SIMPLE_THREAD_POOL-2 ==> is execute  task 7SIMPLE_THREAD_POOL-4 ==> is execute  task 5...

关闭线程池

定义shutdown 方法

public void shutdown() {        while (!TASK_QUEUE.isEmpty()) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        int executors = TASK_EXECUTORS.size();        while (executors > 0) {            for (TaskExecutor taskExecutor : TASK_EXECUTORS) {                if (taskExecutor.getTaskState() == TaskState.BLOCKED) {                    taskExecutor.interrupt();                    taskExecutor.shutdown();                    executors--;                } else {                    try {                        Thread.sleep(50);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }        System.out.println("all threads are dead.");        isShutDown = true;    }

首先判断任务队列是否为空,如果不为空,肯定无法关闭。当任务队列为空时,还需要判断每个执行线程的状态,因为任务可能被分配的到不同的线程中执行,当执行完毕时,则让其生命周期结束。线程池就被关闭了。

定义变量标记是否被shutdown,如果被shutdown,不接受新加入的任务。
private static boolean isShutDown = false;

public void addTask(Runnable runnable) throws Exception {        synchronized (TASK_QUEUE) {            if (isShutDown) {                throw new Exception("thread poll is shutdown.");            }            if (TASK_QUEUE.size() >= TASK_SIZE) {                discardPolicy.discard();            }            TASK_QUEUE.addLast(runnable);            TASK_QUEUE.notifyAll();        }    }

测试

public class SimpleThreadPoolTest {    public static void main(String[] args) throws Exception {        SimpleThreadPool pool = new SimpleThreadPool();        for (int i = 0; i < 20; 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();                }            });        }        pool.shutdown();    }}

输出

SIMPLE_THREAD_POOL-5 ==> is execute  task 4SIMPLE_THREAD_POOL-0 ==> is execute  task 9SIMPLE_THREAD_POOL-1 ==> is execute  task 8SIMPLE_THREAD_POOL-2 ==> is execute  task 7SIMPLE_THREAD_POOL-3 ==> is execute  task 6SIMPLE_THREAD_POOL-8 ==> is execute  task 1SIMPLE_THREAD_POOL-6 ==> is execute  task 3SIMPLE_THREAD_POOL-9 ==> is execute  task 0SIMPLE_THREAD_POOL-7 ==> is execute  task 2SIMPLE_THREAD_POOL-4 ==> is execute  task 5SIMPLE_THREAD_POOL-5 ==> is execute  task 11SIMPLE_THREAD_POOL-1 ==> is execute  task 12SIMPLE_THREAD_POOL-4 ==> is execute  task 19SIMPLE_THREAD_POOL-8 ==> is execute  task 15SIMPLE_THREAD_POOL-3 ==> is execute  task 14SIMPLE_THREAD_POOL-9 ==> is execute  task 17SIMPLE_THREAD_POOL-6 ==> is execute  task 16SIMPLE_THREAD_POOL-0 ==> is execute  task 10SIMPLE_THREAD_POOL-7 ==> is execute  task 18SIMPLE_THREAD_POOL-2 ==> is execute  task 13all threads are dead.

执行完成后退出

完整代码

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<TaskExecutor> TASK_EXECUTORS = new ArrayList<>();    private static final ThreadGroup THREAD_GROUP = new ThreadGroup("Simple_Threadpool_group");    private static int TASK_SIZE;    private static final int TASK_QUEUE_DEFAULT_SIZE = 20;    private static boolean isShutDown = false;    public static final DiscardPolicy DEFAULT_POLICY = () -> {        throw new DiscardException("task size too large.");    };    private final DiscardPolicy discardPolicy;    public SimpleThreadPool() {        this(DEFAULT_SIZE, TASK_QUEUE_DEFAULT_SIZE, DEFAULT_POLICY);    }    public SimpleThreadPool(int size, int taskSize, DiscardPolicy discardPolicy) {        this.size = size;        this.TASK_SIZE = taskSize;        this.discardPolicy = discardPolicy;        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) throws Exception {        synchronized (TASK_QUEUE) {            if (isShutDown) {                throw new Exception("thread poll is shutdown.");            }            if (TASK_QUEUE.size() >= TASK_SIZE) {                discardPolicy.discard();            }            TASK_QUEUE.addLast(runnable);            TASK_QUEUE.notifyAll();        }    }    public void shutdown() {        while (!TASK_QUEUE.isEmpty()) {            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        int executors = TASK_EXECUTORS.size();        while (executors > 0) {            for (TaskExecutor taskExecutor : TASK_EXECUTORS) {                if (taskExecutor.getTaskState() == TaskState.BLOCKED) {                    taskExecutor.interrupt();                    taskExecutor.shutdown();                    executors--;                } else {                    try {                        Thread.sleep(50);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }        System.out.println("all threads are dead.");        isShutDown = true;    }    private TaskExecutor createExecutor() {        TaskExecutor executor = new TaskExecutor(THREAD_GROUP, THREAD_PREFIX + (seq++));        return executor;    }    enum TaskState {        FREE, RUNNING, BLOCKED, DEAD    }    private static class TaskExecutor extends Thread {        private TaskState taskState = TaskState.FREE;        private TaskExecutor(ThreadGroup threadGroup, String name) {            super(threadGroup, name);        }        public TaskState getTaskState() {            return taskState;        }        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) {                            break OUTER;                        }                    }                    runnable = TASK_QUEUE.removeFirst();                }                taskState = TaskState.RUNNING;                runnable.run();                taskState = TaskState.FREE;            }        }        public void shutdown() {            taskState = TaskState.DEAD;        }    }}
@FunctionalInterfacepublic interface DiscardPolicy {    void discard() throws DiscardException;}
public class DiscardException extends Exception {    public DiscardException(String message) {        super(message);    }}
public class SimpleThreadPoolTest {    public static void main(String[] args) throws Exception {        SimpleThreadPool pool = new SimpleThreadPool();        for (int i = 0; i < 20; 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();                }            });        }        pool.shutdown();        pool.addTask(() -> System.out.println("==="));    }}
原创粉丝点击