• java核心知识点 --- 线程池ThreadPool


    线程池是多线程学习中需要重点掌握的.

    系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池.

    一.如何创建线程池??

    在Java5之前,线程池都是开发才手动实现的,从Java5开始,Java内建支持线程池.主要是新增了一个executors工厂类来生产线程池.

    1.newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存到线程池中.

    2.newFixedThreadPool(int nThreads):创建一个可重用的,具有固定线程数的线程池.

    3.newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于调用newFixedThreadPool()方法传入参数为1;

    4.newScheduledThreadPool(int corePoolSize)指池中所保存的线程数,即使线程是空闲的也被保存在线程池内;

    5.newSingleThreadScheduledExecutor():创建只有一个线程的线程池,它可以在指定延迟后执行线程任务;

    上面5个方法中的前3个方法返回一个ExecutorService对象,该对象代表一个线程池,它可以执行Runnable对象或Callable对象所代表的线程;而后2个方法返回一个ScheduledExecutorService线程池,它是ExecutorService的子类.

    二.如何使用线程池?

    举例:

    复制代码
    package com.amos.concurrent;
    
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    /** 
    * @ClassName: ThreadPoolTest 
    * @Description: java5中的线程池
    * @author: amosli
    * @email:hi_amos@outlook.com
    * @date Apr 21, 2014 2:13:27 AM  
    */
    public class ThreadPoolTest {
    
        public static void main(String[] args) {
    //        ExecutorService executorService = Executors.newFixedThreadPool(3);//设置固定的线程数
    //        ExecutorService executorService = Executors.newCachedThreadPool();//创建带缓存的线程池,自动分配线程数
            ExecutorService executorService = Executors.newSingleThreadExecutor();//创建单一线程池,如何实现线程死了,马上自动重新建一个
            Executors.newScheduledThreadPool(3).schedule(new Runnable() {//创建一个有3个线程数的线程池,批定3秒后执行run方法里的内容
                public void run() {
                    System.out.println("bomb.....");
                }
            }, 3, TimeUnit.SECONDS    );//隔3秒
             
            for (int i = 0; i < 10; i++) {//创建10个任务
                final int task = i;
                executorService.execute(new Runnable() {//执行任务的线程
                    public void run() {
                        for (int i = 0; i < 10; i++) {//循环执行10个次
                            System.out.println(Thread.currentThread().getName() + "  loop" + i + " task is" + task);
                        }
                    }
                });
            }
            System.out.println("all of 10 task has committed!!");
            List<Runnable> shutdownNow = executorService.shutdownNow();//立即关闭线程,并返回未执行的线程
            System.out.println("closed thread size:"+shutdownNow.size());
            for(Runnable a:shutdownNow){
                System.out.println(a);
            }
        }
    }
    复制代码

    运行效果:

    创建一个单一的线程池,将任务加入了线程池,被关闭的线程有9个,在3秒后执行了输出'bomb....'

    三.线程池使用注意事项

    1.日常开发中Executors.newFixedThreadPool()是比较常用到的.

    2.如何定时执行任务?

    在执行指定时间执行任务时,比如要在中午12:00时运行一次,那么可以schedule(task, date.getTime() - 
     System.currentTimeMillis(), TimeUnit.MILLISECONDS).也即时采用倒计时的方式去执行定时操作,这个是Java官方文档建议使用的.

    3.扩展---每隔2秒运行一次任务,持续一个小时

    复制代码
    package com.amos.concurrent;
    
    import static java.util.concurrent.TimeUnit.SECONDS;
    
    import java.util.Date;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledFuture;
    
    class BeeperControl {
        private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
        public void beepForAnHour() {
            final Runnable beeper = new Runnable() {
                public void run() {
                System.out.println(new Date().getSeconds());//计时
                System.out.println("beep");
                }
            };
            final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 2, SECONDS);//任务,10s delay,2s/次,单位秒 
            
            scheduler.schedule(new Runnable() {
                public void run() {
                    beeperHandle.cancel(true);//撤消任务
                }
            }, 60 * 60, SECONDS);//60*60s=60min=1h
        }
    }
    public class test{
        public static void main(String[] args) {
            System.out.println(new Date().getSeconds());//计时
            new BeeperControl().beepForAnHour();
        }
    }
    复制代码


    这个例子,是java官方提供的,这里稍做了修改,运行效果如下:

    注:第一次运行是在0秒,10秒后开始第一次beep,然后每隔2秒beep一次;

    这里首先是创建一个任务线程池: Executors.newScheduledThreadPool(1),设置了线程数为1,然后实现了一个runnable接口,再然后就是调用了scheduleAtFixedRate方法,指定频率,指定延时,执行beep任务,最后又实现了一个runnable接口,延时1小时执行撤消线程的任务.

  • 相关阅读:
    ElementUI Select下拉框定位问题!
    Vue2 中keyup.enter触发问题!
    Java编写1到100质数之和
    JSP过滤器、Session监听器、Servlet控制器的关系和执行顺序
    EL表达式读取属性不存在的异常,读取类的属性不存在,无法调用到该属性
    Servlet中使用request转发页面引发的500空指针异常
    JSP动态产生的代码,点击显示确认操作,根据操作跳转并传值。
    Linux常用命令大全
    FastAdmin
    Laravel入门
  • 原文地址:https://www.cnblogs.com/ncy1/p/9164458.html
Copyright © 2020-2023  润新知