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

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

任务加入策略

首先定义策略接口及异常

@FunctionalInterface
public 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 0
SIMPLE_THREAD_POOL-3 ==> is execute  task 6
SIMPLE_THREAD_POOL-2 ==> is execute  task 7
SIMPLE_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 4
SIMPLE_THREAD_POOL-0 ==> is execute  task 9
SIMPLE_THREAD_POOL-1 ==> is execute  task 8
SIMPLE_THREAD_POOL-2 ==> is execute  task 7
SIMPLE_THREAD_POOL-3 ==> is execute  task 6
SIMPLE_THREAD_POOL-8 ==> is execute  task 1
SIMPLE_THREAD_POOL-6 ==> is execute  task 3
SIMPLE_THREAD_POOL-9 ==> is execute  task 0
SIMPLE_THREAD_POOL-7 ==> is execute  task 2
SIMPLE_THREAD_POOL-4 ==> is execute  task 5
SIMPLE_THREAD_POOL-5 ==> is execute  task 11
SIMPLE_THREAD_POOL-1 ==> is execute  task 12
SIMPLE_THREAD_POOL-4 ==> is execute  task 19
SIMPLE_THREAD_POOL-8 ==> is execute  task 15
SIMPLE_THREAD_POOL-3 ==> is execute  task 14
SIMPLE_THREAD_POOL-9 ==> is execute  task 17
SIMPLE_THREAD_POOL-6 ==> is execute  task 16
SIMPLE_THREAD_POOL-0 ==> is execute  task 10
SIMPLE_THREAD_POOL-7 ==> is execute  task 18
SIMPLE_THREAD_POOL-2 ==> is execute  task 13
all 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;
        }
    }


}
@FunctionalInterface
public 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("==="));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值