一个简单的java线程池

来源:互联网 发布:unity3d 角色动作 编辑:程序博客网 时间:2024/05/29 09:54
import java.util.Vector;public class SimpleThreadPool {    /* 线程池中的 Trhead 数量 */    private static final Integer NTHREADS = 3;    /* 线程池实例 */    private static SimpleThreadPool threadPool;    private Vector<PThread> pthreads = new Vector<>();    private Vector<Runnable> runnables = new Vector<>();    /* 初始化线程池 */    private SimpleThreadPool() {        for (int i = 0; i < NTHREADS; ++i)            pthreads.add(new PThread(i));        for (PThread pthread : pthreads)            pthread.start();    }    /* 简单的单例模式线程池 */    public static synchronized SimpleThreadPool getInstance() {        if (threadPool == null)            threadPool = new SimpleThreadPool();        return threadPool;    }    /*     * 向线程池提交一个任务(runnable, 或task)     * 并且唤醒池中的一个睡眠线程,     *     * 如果线程池中没有空闲线程, 这个notify信号将会"丢失".     * 但是这不影响线程池的功能,     * 因为当一个线程结束任务的时候, 它会主动检查任务队列(runnables), 以查看是否有挂起的任务     *     * 这个地方, runnables.size() 实际上为我们提供了一个 "唤醒信号计数器", 里面记录了唤醒信号的数目,     * 所以, 严格地说, 其实唤醒信号并不会丢失.     *     * 这是一种常见的多线程模式:     * 1. 为唤醒信号提供一个计数器     * 2. 线程睡眠之前总是先检查唤醒信号计数器     */    public void submit(Runnable runnable) {        synchronized (runnables) {            System.out.printf("summit runnable %d.\n", ((SimpleRunnable)runnable).getID());            runnables.add(runnable);            runnables.notify();        }    }    /* 线程池中的工作线程     *     * 这些线程完成其任务后不会退出, 而是马不停蹄地执行任务队列(runnables)中的下一个任务,     * 如果任务队列中没有任务, 那么此线程将主动睡眠, 直到新的任务到来, 并将其唤醒.     */    class PThread extends Thread {        private Integer id;        public PThread(Integer id) {            this.id = id;        }        @Override        public void run() {            Runnable runnable;            /*             * 如果要实现线程池的销毁功能, 请在线程池中额外实现一个变量, 比如disabled,             * 然后将while(true)替换为while(!disabled);             */            while (true) {                synchronized (runnables) {                        /*                         * 被唤醒的工作线程将重新检查当初导致其阻塞的条件,                         * 考虑到以下过程, 这是非常必要的.                         *                         * 1. 线程0被创建, 发现runnables.empty()==ture, 睡眠                         * 2. 一个任务, 比如任务0, 被插入到任务队列(runnables), 向睡眠的线程发送信号.                         * 3. 线程1被创建, 发现runnables.size()==1, 删除这个任务, 因为线程1随后就要执行这个任务                         * 4. 线程0被第(2)步中的信号唤醒, 此时任务0已经被线程1执行.                         *                         * 考虑第(4)步, 如果线程0醒来后不检查 睡眠条件, 那么线程0再次执行任务0, 导致不可知的行为.                         */                       while (runnables == null || runnables.isEmpty()) {                            try {                                System.out.printf("Thread#%d going to sleep.\n", id);                                runnables.wait();                            } catch (InterruptedException ie) {                            }                        }                        runnable = runnables.remove(0);                }                /* 小细节: 在外部执行任务 */                System.out.printf("Thread#%d waking up with runnable#%d\n", id, ((SimpleRunnable)runnable).getID());                runnable.run();            }        }    }    /* 测试 */    public static void main(String args[]) throws InterruptedException {        Thread.sleep(100);        for (int i = 0; i < 10; ++i) {            SimpleThreadPool.getInstance().submit(new SimpleRunnable(i));            Thread.sleep(100);        }    }    /* 测试 */    static class SimpleRunnable implements Runnable {        private Integer id;        public SimpleRunnable(Integer id) {            this.id = id;        }        public Integer getID() {            return id;        }        @Override        public void run() {            System.out.printf("Runnable #%d passing by.\n", id);            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.printf("Runnable #%d quit.\n", id);        }    }}