zoukankan      html  css  js  c++  java
  • 简单实现java线程池 阿里

    使用多线程以及线程池的意义无需多说,要想掌握线程池,最好的方法还是自己手动去实现。

     

    一、实现思路

                          (网络盗图)

     

    二、实现代码

    1、线程池类

    package com.ty.thread;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    /**
     * @author Taoyong
     * @date 2018年5月17日
     * 天下没有难敲的代码!
     */
    public class ThreadPoolExecutor {
        
        /*
         * BlockingQueue是阻塞队列,在两种情况下出现阻塞:
         *     1、当队列满了,入队列操作时;
         *     2、当队列空了,出队列操作时。
         * 阻塞队列是线程安全的,主要使用在生产/消费者的场景
         */
        private BlockingQueue<Task> blockingQueue;
        
        //线程池的工作线程数(可以认为是线程池的容量)
        private int poolSize = 0;
        
        //线程池的核心容量(也就是当前线程池中真正存在的线程个数)
        private int coreSize = 0;
        
        /*
         * 此地方使用volatile关键字,volatile的工作原理是:对于JVM维度来说,每个线程持有变量的工作副本,那对于计算机维度来说,
         * 就是这些变量的中间值会存放在高速缓存中。通过volatile关键字,告知每个线程改变此变量之后,立马更新到内存中去,并且使得
         * 缓存中的数据失效,这样来保证其中某个线程改变公有变量后,其他线程能及时读取到最新的变量值,从而保证可见性。
         * 原因如下:
         *     1、在ThreadPoolExecutorTest中操作shutDown,这是main线程操作此变量(由于变量是volatile声明,所以会立马写入内存中);
         *     2、Worker中线程通过while(!shutDown)来判断当前线程是否应该关闭,因此需通过volatile保证可见性,使线程可以及时得到关闭。
         */
        private volatile boolean shutDown = false;
        
        public ThreadPoolExecutor(int size) {
            this.poolSize = size;
            //LinkedBlockingQueue的大小可以指定,不指定即为无边界的。
            blockingQueue = new LinkedBlockingQueue<>(poolSize);
        }
        
        public void execute(Task task) throws InterruptedException {
            if(shutDown == true) {
                return;
            }
            
            if(coreSize < poolSize) {
                /*
                 * BlockingQueue中的插入主要有offer(obj)以及put(obj)两个方法,其中put(obj)是阻塞方法,如果插入不能马上进行,
                 * 则操作阻塞;offer(obj)则是插入不能马上进行,返回true或false。
                 * 本例中的Task不允许丢失,所以采用put(obj);
                 */
                blockingQueue.put(task);
                produceWorker(task);
            }else {
                blockingQueue.put(task);
            }
        }
    
        private void produceWorker(Task task) throws InterruptedException {
            if(task == null) {
                throw new NullPointerException("非法参数:传入的task对象为空!");
            }
    
            Thread thread = new Thread(new Worker());        
            thread.start();
            coreSize++;
        }
        
        /*
         * 真正中断线程的方法,是使用共享变量发出信号,告诉线程停止运行。
         * 
         */
        public void shutDown() {
            shutDown = true;
        }
        
        /*
         * 此内部类是实际上的工作线程
         * 
         */
        class Worker implements Runnable {
    
            @Override
            public void run() {        
                while(!shutDown) {    
                    try {
                        //
                        blockingQueue.take().doJob();
                    } catch (InterruptedException e) {                    
                        e.printStackTrace();
                    }
                }            
                System.out.println("线程:" + Thread.currentThread().getName() + "退出运行!");
            }    
        }
    }

     

    2、Task类(需要被线程处理的任务类)

    package com.ty.thread;
    
    /**
     * @author Taoyong
     * @date 2018年5月17日
     * 天下没有难敲的代码!
     */
    public class Task {
    
        //通过taskId对任务进行标识
        private int taskId;
        
        public Task(int taskId) {
            this.taskId = taskId;
        }
    
        public void doJob() {
            System.out.println("线程" + Thread.currentThread().getName() + "正在处理任务!");
        }
    
        public int getId() {        
            return taskId;
        }
    }

     

     3、测试类

    package com.ty.thread;
    
    /**
     * @author Taoyong
     * @date 2018年5月17日
     * 天下没有难敲的代码!
     */
    public class ThreadPoolExecutorTest {
    
        public static void main(String[] args) throws InterruptedException {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3);
            for(int i = 0; i < 10; i++) {
                Task task = new Task(i);
                threadPoolExecutor.execute(task);                
            }        
            
            threadPoolExecutor.shutDown();
        }
    }

     

    4、运行结果

    线程Thread-0正在处理任务!
    线程Thread-1正在处理任务!
    线程Thread-0正在处理任务!
    线程Thread-1正在处理任务!
    线程Thread-2正在处理任务!
    线程Thread-0正在处理任务!
    线程Thread-1正在处理任务!
    线程:Thread-1退出运行!
    线程:Thread-0退出运行!
    线程Thread-2正在处理任务!
    线程:Thread-2退出运行!

     

    当第十个任务待处理时,整个线程池已经被shutDown,整个流程结束。

    项目代码已经上传到github中:https://github.com/ali-mayun/threadPool

    如果想给予我更多的鼓励,求打

    因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【阿里马云】!

  • 相关阅读:
    Python代码项目目录规范v1.0
    博客自定义
    Linux之查看CPU信息
    Python字符界面函数库
    数组的遍历你都会用了,那Promise版本的呢
    NPM实用指北
    如何从0开发一个Atom组件
    使用JavaScript实现一个俄罗斯方块
    使用PostMan进行API自动化测试
    一个有味道的函数
  • 原文地址:https://www.cnblogs.com/alimayun/p/9054027.html
Copyright © 2011-2022 走看看