zoukankan      html  css  js  c++  java
  • 线程池小结(二)

    关于线程池的介绍,请看上一篇博客:http://www.cnblogs.com/DarrenChan/p/5774921.html

    1. 线程池的5中创建方式

    1) Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,

    代码: Executors.newSingleThreadExecutor()

    2) Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,

    代码:Executors.newCachedThreadPool()

    3) Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,

    代码: Executors.newFixedThreadPool(4)

    在构造函数中的参数4是线程池的大小,你可以随意设置,也可以和cpu的核数量保持一致,获取cpu的核数量int cpuNums = Runtime.getRuntime().availableProcessors();

    4) Scheduled Thread Pool : 用来调度即将执行的任务的线程池,可能是不是直接执行, 每隔多久执行一次... 策略型的

    代码:Executors.newScheduledThreadPool()

    5) Single Thread Scheduled Pool : 只有一个线程,用来调度任务在指定时间执行,代码:Executors.newSingleThreadScheduledExecutor()

    使用代码小结:

    package cn.itcast_01_mythread.pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    
    /**
     * 列出并发包中的各种线程池
     * @author
     *
     */
    
    public class ExecutorDemo {
        
        public static void main(String[] args) {
            ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
            ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
            
            int cpuNums = Runtime.getRuntime().availableProcessors();//电脑的核心数
            System.out.println(cpuNums);
            ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(cpuNums);
            ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(8);
            
            ScheduledExecutorService newSingleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        }
    }

    2. 线程池的使用

    1)提交 Runnable ,任务完成后 Future 对象返回 null

    调用submit,提交任务, 匿名Runable重写run方法, run方法里是业务逻辑(调用execute()提交任务也可以)

    package cn.itcast_01_mythread.pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadPoolWithRunable {
    
        
        /**
         * 通过线程池执行线程
         * @param args
         */
        public static void main(String[] args) {
            //创建一个线程池
            ExecutorService pool = Executors.newCachedThreadPool();
            for(int i = 0; i < 5; i++){
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("thread name: " + Thread.currentThread().getName());
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            pool.shutdown();
        }
    
    }

    运行结果:

    thread name: pool-1-thread-1
    thread name: pool-1-thread-5
    thread name: pool-1-thread-3
    thread name: pool-1-thread-2
    thread name: pool-1-thread-4

    2) 提交 Callable,该方法返回一个 Future 实例表示任务的状态

    调用submit提交任务, 匿名Callable,重写call方法, 有返回值, 获取返回值会阻塞,一直要等到线程任务返回结果

    调用submit提交任务,有Future返回值,里面可以传Callable对象或者Runnable对象

    package cn.itcast_01_mythread.pool;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * callable 跟runnable的区别: runnable的run方法不会有任何返回结果,所以主线程无法获得任务线程的返回值
     * 
     * callable的call方法可以返回结果,但是主线程在获取时是被阻塞,需要等待任务线程返回才能拿到结果
     * 
     * @author
     * 
     */
    public class ThreadPoolWithcallable {
    
        public static void main(String[] args) throws InterruptedException,
                ExecutionException {
            ExecutorService pool = Executors.newFixedThreadPool(4);
    
            for (int i = 0; i < 10; i++) {
                Future<String> submit = pool.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        // System.out.println("a");
                        Thread.sleep(5000);
                        return "b--" + Thread.currentThread().getName();
                    }
                });
                // 从Future中get结果,这个方法是会被阻塞的,一直要等到线程任务返回结果
                System.out.println(submit.get());
            }
            pool.shutdown();
    
        }
    
    }

    运行结果:

    b--pool-1-thread-1
    b--pool-1-thread-2
    b--pool-1-thread-3
    b--pool-1-thread-4
    b--pool-1-thread-1
    b--pool-1-thread-2
    b--pool-1-thread-3
    b--pool-1-thread-4
    b--pool-1-thread-1
    b--pool-1-thread-2

    再观察一个简单例子:

    TaskRunnable.java:

    package cn.itcast_01_mythread.pool;
    
    import java.util.Random;
    
    public class TaskRunnable implements Runnable{
        private int s;
        
        public TaskRunnable(int s){
            this.s = s;
        }
        
        Random r = new Random();
        
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            long currentTimeMillis = System.currentTimeMillis();
            System.out.println(name+" 启动时间:" + currentTimeMillis/1000);
            
            int rint = r.nextInt(3);
            try {
                Thread.sleep(rint*1000);
            } catch (InterruptedException e) {
                 
                e.printStackTrace();
            }
            System.out.println(name + " is working..."+s);
            
        }
    
    }

    TaskCallable.java:

    package cn.itcast_01_mythread.pool;
    
    import java.util.Random;
    import java.util.concurrent.Callable;
    
    public class TaskCallable implements Callable<String> {
    
        private int s;
        Random r = new Random();
    
        public TaskCallable(int s) {
            this.s = s;
        }
    
        @Override
        public String call() throws Exception {
            String name = Thread.currentThread().getName();
            long currentTimeMillis = System.currentTimeMillis();
            System.out.println(name + " 启动时间:" + currentTimeMillis / 1000);
    
            int rint = r.nextInt(3);
            try {
                Thread.sleep(rint * 1000);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            System.out.println(name + " is working..." + s);
            return s + "";
        }
    
    }

    TestPool.java:

    package cn.itcast_01_mythread.pool;
    
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class TestPool {
    
        public static void main(String[] args) throws Exception {
            Future<?> submit = null;
            Random random = new Random();
            
            //创建固定数量线程池
    //        ExecutorService exec = Executors.newFixedThreadPool(4);
            
            //创建调度线程池
            ScheduledExecutorService exec = Executors.newScheduledThreadPool(4);
            
            //用来记录各线程的返回结果
            ArrayList<Future<?>> results = new ArrayList<Future<?>>();
            
            for (int i = 0; i < 10; i++) {
                //fixedPool提交线程,runnable无返回值,callable有返回值
                /*submit = exec.submit(new TaskRunnable(i));*/
                /*submit = exec.submit(new TaskCallable(i));*/
                
                //对于schedulerPool来说,调用submit提交任务时,跟普通pool效果一致
                /*submit = exec.submit(new TaskCallable(i));*/
                //对于schedulerPool来说,调用schedule提交任务时,则可按延迟,按间隔时长来调度线程的运行
                submit = exec.schedule(new TaskCallable(i), random.nextInt(10), TimeUnit.SECONDS);
                //存储线程执行结果
                results.add(submit);
                
            }
            
            //打印结果
            for(Future f: results){
                boolean done = f.isDone();
                //从结果的打印顺序可以看到,即使未完成,也会阻塞等待
                System.out.println((done?"已完成":"未完成")+"====线程返回future结果: " + f.get());
            }
            exec.shutdown();
        }
    }

    运行结果:

    pool-1-thread-1 启动时间:1489198939
    pool-1-thread-1 is working...4
    pool-1-thread-4 启动时间:1489198942
    pool-1-thread-3 启动时间:1489198943
    pool-1-thread-4 is working...5
    pool-1-thread-2 启动时间:1489198945
    pool-1-thread-4 启动时间:1489198945
    pool-1-thread-1 启动时间:1489198945
    pool-1-thread-4 is working...6
    pool-1-thread-3 is working...8
    pool-1-thread-1 is working...3
    pool-1-thread-4 启动时间:1489198946
    pool-1-thread-4 is working...2
    pool-1-thread-2 is working...1
    pool-1-thread-3 启动时间:1489198947
    pool-1-thread-3 is working...7
    pool-1-thread-1 启动时间:1489198948
    pool-1-thread-1 is working...0
    pool-1-thread-4 启动时间:1489198948
    未完成====线程返回future结果: 0
    已完成====线程返回future结果: 1
    已完成====线程返回future结果: 2
    已完成====线程返回future结果: 3
    已完成====线程返回future结果: 4
    已完成====线程返回future结果: 5
    已完成====线程返回future结果: 6
    已完成====线程返回future结果: 7
    已完成====线程返回future结果: 8
    pool-1-thread-4 is working...9
    未完成====线程返回future结果: 9

  • 相关阅读:
    AC 自动机
    [HihoCoder-1424] Asa's Chess Problem
    C++ Tricks
    2017"百度之星"程序设计大赛
    后缀自动机
    ASP教程:gb2312和utf-8乱码问题解决
    cryto-js 常用加密库 md5加密
    nrm是什么?以及nrm的安装与命令
    MongoDB 安装
    koa2 安装与启动
  • 原文地址:https://www.cnblogs.com/DarrenChan/p/6533644.html
Copyright © 2011-2022 走看看