zoukankan      html  css  js  c++  java
  • 线程池

    工具类:

    • 缓冲线程池:Executors.newCachedThreadPool();
      可以根据新加入任务自动调整线程池大小,没有任务队列
      源码:
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>()); // 无容量的任务队列
        }
    
    • 固定容量的线程池:Executors.newFixedThreadPool(3);
      创建固定大小的线程池,新任务添加到任务队列
      源码:
    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>()); // 无界的任务队列
    
    • 定义只有一个线程的线程池:Executors.newSingleThreadExecutor();
      源码:
    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    

    线程池创建方法

    1.工具类,不推荐
    Executors 返回线程池对象的弊端如下:
    FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE ,可能堆积大量的请求,从而导致OOM。
    CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。
    所有Executors返回的线程池类型,都是由WhreadPoolExecutor实现
    2.ThreadPoolExecutor类,推荐
    构造方法:
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)

    线程池的启动策略:

    1、线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也
    不会马上执行它们。
    2、当调用 execute() 方法添加一个任务时,线程池会做如下判断:
    a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
    b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
    c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这
    个任务;
    d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告
    诉调用者“我不能再接受任务了”。
    3、当一个线程完成任务时,它会从队列中取下一个任务来执行。
    4、当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于
    corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

    Callable 实现线程池Demo

    		ExecutorService pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
    		long statr = System.currentTimeMillis();
    		for (int i = 0; i < 1000; i++) {
    			Future<Integer> result= pool.submit(new Call(i)); // 线程的返回值类型为Future<>;
    			try {
    				System.out.println(result.get(1000, TimeUnit.SECONDS)); // 取出返回值
    			} catch (InterruptedException | ExecutionException | TimeoutException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			
    		}
    

    submit() 和 excute()方法的区别

    • excute()传入实现了Runnable接口的对象,submit传入实现了Callable<>接口的对象,泛型为返回值类型
    • excute()没有返回值, submit()返回一个Future<>类型的值,泛型为传入Callable的返回值

    自定义线程池ThreadPoolExcutExecutor类的参数含义

    /**参数含义
    * corePoolSize 核心线程池大小
    * maximumPoolSize 最大线程池大小
    * keepAliveTime 当线程数大于核心时,此为终止前多余的空闲等待新任务最长间。
    * TimeUnit keepAliveTime的时间单位
    * workQueue 阻塞队列
    *
    */

  • 相关阅读:
    mysql-5.7.15-winx64免安装版配置
    db2 表授权语句
    java 调用 .net webservice 示例
    打印内存高解决方案
    eclipse快捷键调试总结【转】
    DevExpress GridControl 自定义 summary 算法
    GEMR: Get the parent window for view
    弹出窗口
    WPF UI虚拟化
    WPF应用程序最小化到系统托盘
  • 原文地址:https://www.cnblogs.com/zhz-8919/p/10815042.html
Copyright © 2011-2022 走看看