并发-线程池-2-ThreadPoolExecutor框架

自定义线程池使用详细:

JDK底层ThreadPoolExecutor的构造方法实现:
其中核心内容是BlockingQueue<Runnable> workQueue,之所以Exectuors拥有创建不同类型的线程池关键在于此处传入的参数可以时不同的队列。
也就是说当Exectuors不能满足你的话,可以根据这个方法自定义自己的线程池:

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                     long keepAliveTime,
                     TimeUnit unit,
      BlockingQueue<Runnable> workQueue,
      ThreadFactory threadFactory,
      RejectedExecutionHandler handler) 
      {...}

构造方法对于队列时什么类型的十分关键:
1、使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,则会将任务会被加入队列。若队列已经满了,则总线程数不大于maximumPoolSize的前提下,创建新线程执行任务,如果线程数量大于maximumPoolSize,则执行拒绝策略,或者一些其他自定义的方式。

2、无界的任务队列:LinkedBlockingQueue.于有界队列相比,除非系统资源耗尽,否则无界队列不会存在任务加入队列失败的情况。当有新的任务到来系统的线程数小于corePoolSize,则会创建线程执行任务。当达到corePoolSize后,就不会继续增加。若后续仍有新的任务加入,而又没空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。

JDK拒绝策略:
AbortPolicy:直接抛出异常,组织系统正常工作。
CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。
DiscardOldestPolicy:丢弃无法处理的任务,不给予任何处理。
如果需要自定义拒绝策略可以实现RejectedExecutionHandler接口

有界队列样例:


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author zhanghuilong
 * @version V1.0
 * @desc
 * @since 2018/01/06
 */
public class MyThreadLocal {

    /**
     * 若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
     * 若大于corePoolSize,则会将任务会被加入队列。
     * 若队列已经满了,则总线程数不大于maximumPoolSize的前提下,创建新线程执行任务,
     * 如果线程数量大于maximumPoolSize,则执行拒绝策略
     */
    public static void main(String[] args) {
        //创建一个核心线程数1,最大允许线程数2,有界队列3的自定义线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            1, // 核心线程数
            2, // 最大允许线程数
            60, TimeUnit.SECONDS,
            // 有界队列最大值
            new ArrayBlockingQueue<Runnable>(3));

        Task task1 = new Task(1, "t1");
        Task task2 = new Task(2, "t2");
        Task task3 = new Task(3, "t3");
        Task task4 = new Task(4, "t4");
        Task task5 = new Task(5, "t5");
        //Task task6 = new Task(6,"t6");


        threadPoolExecutor.execute(task1);
        threadPoolExecutor.execute(task2);
        threadPoolExecutor.execute(task3);
        threadPoolExecutor.execute(task4);
        threadPoolExecutor.execute(task5);
        //threadPoolExecutor.execute(task6);

        // 停止线程
        threadPoolExecutor.shutdown();
    }

    static class Task implements Runnable {
        private int id;
        private String name;

        @Override
        public void run() {
            try {
                System.out.println("run taskid:" + this.id);
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public Task(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

}

当执行5条任务时,打印结果:

这里写图片描述
⚠️:现打印的1和5
执行第1个任务时,任务数没有超过核心线程数,所以线程优先执行,第2个任务进来时,超过了核心线程数,然后入队列,之后的3,4都加入到了队列,队列最大存储3个,然后第5个任务来的时候,线程池开始启用最大允许线程数的概念,创建了一个新的线程去执行5.当1,5执行完毕,开始从队列中获取任务,2,3,4。

当我们打开注释的任务6时,再次执行发现触发了拒绝策略:

这里写图片描述

使用无界队列样例:

package com.huilong.study.apple.service.executor;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhanghuilong
 * @version V1.0
 * @desc
 * @since 2018/01/06
 */
public class MyThreadLocal2 {
    static class MyTask implements Runnable {

        private static AtomicInteger count = new AtomicInteger(0);

        @Override
        public void run() {
            try {
                int get = count.incrementAndGet();
                System.out.println("任务:" + get);
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public AtomicInteger getCount() {
            return count;
        }

        public void setCount(AtomicInteger count) {
            this.count = count;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 声明无界队列
        LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,//核心线程数
            10000,
            60L,
            TimeUnit.SECONDS,
            queue);
       // 20个任务
        for (int i = 0; i < 20; i++) {
            threadPoolExecutor.execute(new MyTask());
        }
        Thread.sleep(1000);
        System.out.println("queue size = [" + queue.size() + "]");
        Thread.sleep(2000);
    }
}

输出结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/java_huilong/article/details/78992084
今日推荐