zoukankan      html  css  js  c++  java
  • Java线程池的实现

    线程池的作用:

    一个线程的周期分为:创建、运行、销毁三个阶段。

    处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程。而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个阶段才是有效运行时间

    所以,我们希望花在创建和销毁线程的资源越少越好。如果不销毁线程,而这个线程又不能被其他的任务调用,那么就会出现资源的浪费。为了提高效率,减少创建和销毁线程带来时间和空间上的浪费,出现了线程池技术。这种技术是在开始就创建一定量的线程,批量处理一类任务,等待任务的到来。任务执行完毕后,线程又可以执行其他的任务。等不再需要线程的时候,就销毁。这样就省去了频繁创建和销毁线程的麻烦。

    1. 线程池类

    import java.util.LinkedList;
    import java.util.List;
    
    public class MyThreadPool {
        // 线程池中默认线程的个数为5个
        private static int worker_num = 5;
        // 工作的线程
        private WorkThread[] workThreads;
        // 未处理的任务
        private static volatile int finished_task = 0;
        // 任务队列,作为一个缓冲,List线程不安全所以需要在使用的过程中对它进行同步。
        private List<Runnable> taskQueue = new LinkedList<Runnable>();
        
        // 单例模式
        private static MyThreadPool threadPool;
        // 私有化构造方法
        private MyThreadPool(){
            this(5);
        }
        // 创建线程池,num为线程池工作线程的个数
        private MyThreadPool(int num) {
            MyThreadPool.worker_num = num;
            workThreads = new WorkThread[num];
            for (int i = 0; i < num; i++) {
                workThreads[i] = new WorkThread();
                workThreads[i].start();
            }
        }
        
        // 获得一个线程池,默认线程数
        public static MyThreadPool getThreadPool(){
            return getThreadPool(MyThreadPool.worker_num);
        }
        // 单例模式,获得一个线程池
        public static MyThreadPool getThreadPool(int num) {
            if(num <= 0){
                num = MyThreadPool.worker_num;
            }
            if(threadPool == null){
                synchronized(MyThreadPool.class){
                    if(threadPool == null)
                        threadPool = new MyThreadPool(num);
                }
            }
            return threadPool;
        }
    
        /**
         * 执行任务
         * 将该任务加入到任务队列的末尾,等待工作线程的调度
         * @param task
         */
        public void execute(Runnable task){
            synchronized (taskQueue){
                taskQueue.add(task);
                taskQueue.notify();
            }
        }
        
        /**
         * 批量执行任务
         * 将任务放到任务队列的末尾,等待工作线程的调度
         * @param task
         */
        public void execute(Runnable[] task){
            synchronized (taskQueue){
                for (Runnable runnable : task) {
                    taskQueue.add(runnable);
                }
                taskQueue.notify();
            }
        }
        
        /**
         * 批量执行任务
         * 将任务放到任务队列的末尾,等待工作线程的调度
         * @param task
         */
        public void execute(List<Runnable> task){
            synchronized (taskQueue){
                for (Runnable runnable : task) {
                    taskQueue.add(runnable);
                }
                taskQueue.notify();
            }
        }
        
        /**
         * 销毁线程池
         * 在所有任务都完成的情况下才销毁所有线程,否则等待任务队列的任务全部完成才销毁
         */
        public void destroy(){
            while(!taskQueue.isEmpty()){// 如果还有任务没执行完成,就等会再看看
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            // 工作线程停止工作,且置为null
            for (int i = 0; i < MyThreadPool.worker_num; i++) {
                workThreads[i].stopWorker();
                workThreads[i] = null;
            }
            threadPool = null;
            taskQueue.clear();
        }
        
        // 返回工作线程的个数
        public int getWorkThreadNumber() {
            return worker_num;
        }
        
        // 返回已完成任务的个数
        public int getFinishedTaskNumber(){
            return finished_task;
        }
        
        // 返回任务队列的长度,即还没处理的任务个数
        public int getWaitTaskNumber(){
            return taskQueue.size();
        }
        
        // 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数  
        @Override  
        public String toString() {  
            return "WorkThread number:" + worker_num + "  finished task number:"  
                    + finished_task + "  wait task number:" + getWaitTaskNumber();  
        }
        
        /**
         * 内部类,工作线程用来执行任务线程
         * @author liu
         *
         */
        private class WorkThread extends Thread{
            // 该工作线程是否有效,用于自然结束该工作线程
            private boolean isRunning = true;
            
            /* 
             * 工作线程的关键之处,如果任务队列不空,则取出任务执行,若任务队列空,则等待。直到任务队列有任务时才取出执行
             */
            @Override
            public void run() {
                Runnable r = null;
                while( isRunning ){// 队列为空
                    synchronized (taskQueue){
                        while(isRunning && taskQueue.isEmpty()){
                            try {
                                taskQueue.wait(20);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        
                        if(!taskQueue.isEmpty()){
                            // 取出任务
                            r = taskQueue.remove(0);
                        }
                    }
                    
                    if(r != null){
                        r.run();
                        // 完成的任务加一
                        finished_task += 1;
                    }
                    
                    r = null;
                }
            }
            
            // 停止工作,让该线程自然执行完run方法,自然结束 
            public void stopWorker() {
                this.isRunning = false;
            }
            
        }
    }

     2. 测试代码

    public class TestThreadPool {
    
        public static void main(String[] args) {
            // 创建5个线程的线程池  
            MyThreadPool t = MyThreadPool.getThreadPool(5);
            Runnable[] r = new Runnable[] { new Task(), new Task(), new Task()};
            t.execute(r);
            r = new Runnable[] {new Task(), new Task(), new Task()};
            t.execute(r);  
            System.out.println(t);
            t.destroy();// 所有线程都执行完成才destory  
            System.out.println(t); 
        }
        
        // 任务类
        static class Task implements Runnable {  
            private static volatile int i = 1;
      
            @Override  
            public void run() {// 执行任务  
                System.out.println("任务 " + (i++) + " 完成");  
            }
        }
    }

    3. 运行结果

    注:参照网上的代码和思路,通过自己的修改和调试完成

  • 相关阅读:
    CSS系列:长度单位&字体大小的关系em rem px
    CSS兼容性
    html5+css3
    将url的查询参数解析成字典对象
    SQL阻止保存要求重新创建表的更改 在哪里设置
    Jquery&JS简单选项卡
    块级&行内(内联)元素
    时间
    PHP 二维数组根据某个字段排序
    php 操作数组 (合并,拆分,追加,查找,删除等)
  • 原文地址:https://www.cnblogs.com/liuleicode/p/5492724.html
Copyright © 2011-2022 走看看