线程池之ThreadPoolExecutor

目录

1.ThreadPoolExecutor构造函数

2.BlockingQueue workQueue参数详解

3.ThreadPoolExecutor执行任务demo

4.利用submit去提交任务

5.自定义ThreadPoolExecutor


上一篇说了多线程开发和4种常见的线程池:https://blog.csdn.net/qq_37321098/article/details/82781885

1.ThreadPoolExecutor构造函数

我们看一下FixedThreadPool的实例化:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

所以说,4种常见的线程池都是对ThreadPoolExecutor配置不同而已。下面主要看看它参数最全的构造方法:

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

参数含义如下:

corePoolSize  线程池中核心线程的数量,即能够同时执行的任务数量

maximumPoolSize  线程池中最大线程数量。当我们每添加一个任务,如当线程数小于corePoolSize时,则立即开启线程执行;当corePoolSize满的时候,后面添加的任务将放入缓冲队列workQueue等待;当workQueue也满的时候,看是否超过maximumPoolSize线程数,如果超过,默认拒绝执行(比如corePoolSize为2且已满,maximumPoolSize为3,workQueue满了,此时来2个任务,会开启1个非核心线程去运行1个任务,至于还有1个任务,由于超出maximumPoolSize数量,会被拒绝执行)。 

keepAliveTime 非核心线程的超时时长,当系统中非核心线程闲置时间超过keepAliveTime之后,则会被回收。如果ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,则该参数也表示核心线程的超时时长

unit 第三个参数的单位,有纳秒、微秒、毫秒、秒、分、时、天等

workQueue 线程池中的任务队列,该队列主要用来存储已经被提交但是尚未执行的任务。

threadFactory  为线程池提供创建新线程的功能,一般使用默认即可

handler 拒绝添加新任务策略,当线程无法执行新任务时(一般是由于线程池中的线程数量已经达到最大数或者线程池关闭导致的),默认情况下,当线程池无法处理新线程时,会抛出一个RejectedExecutionException。

2.BlockingQueue<Runnable> workQueue参数详解

BlockingQueue阻塞队列存放待执行任务,BlockingQueue有多种不同的实现类:

1)ArrayBlockingQueue:规定了大小的BlockingQueue,构造函数的int值可设置大小,任务执行顺序为先进先出

2)LinkedBlockingQueue:大小不确定的BlockingQueue,构造方法中可传一个int值去规定队列大小,也可以不传,默认的大小就为Integer.MAX_VALUE

3)PriorityBlockingQueue:和LinkedBlockingQueue类似,不同的是PriorityBlockingQueue中的任务不是先进先出规则,而是按照Comparator来决定存取顺序的(因此存入PriorityBlockingQueue中的数据必须实现Comparator接口)。

4)SynchronousQueue:同步的BlockingQueue,属于线程安全的。https://blog.csdn.net/zmx729618/article/details/52980158

3.ThreadPoolExecutor执行任务demo

   //创建核心线程3,最大线程3,超时时长1s,容量100的LinkedBlockingDeque队列
        final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 3,
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(100));

        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for (int i = 0; i < 10; i++) {
                    poolExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            SystemClock.sleep(1000);
                        }
                    });
                }
            }
        });

运行结果如下:

//12s的时候,执行2任务
13:54:12.096 30856-31644/com.bihucj.mcandroid E/任务:: 1
13:54:12.096 30856-31643/com.bihucj.mcandroid E/任务:: 0

//13s的时候,执行2任务
13:54:13.096 30856-31644/com.bihucj.mcandroid E/任务:: 3
13:54:13.097 30856-31643/com.bihucj.mcandroid E/任务:: 2

此时我们改一下ThreadPoolExecutor参数为:

 final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 5,
                1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(5));

运行结果如下:

//核心线程执行2任务,然后5个任务放到队列,有剩下的3个非核心线程执行顺序较后的3任务
13:59:49.471 9064-9337/com.bihucj.mcandroid E/任务:: 0
13:59:49.471 9064-9338/com.bihucj.mcandroid E/任务:: 1
13:59:49.483 9064-9339/com.bihucj.mcandroid E/任务:: 7
13:59:49.484 9064-9340/com.bihucj.mcandroid E/任务:: 8
13:59:49.484 9064-9341/com.bihucj.mcandroid E/任务:: 9

//队列中任务开始执行
13:59:50.471 9064-9337/com.bihucj.mcandroid E/任务:: 2
13:59:50.472 9064-9338/com.bihucj.mcandroid E/任务:: 3
13:59:50.484 9064-9339/com.bihucj.mcandroid E/任务:: 4
13:59:50.484 9064-9340/com.bihucj.mcandroid E/任务:: 5
13:59:50.485 9064-9341/com.bihucj.mcandroid E/任务:: 6

模仿AsyncTask设置参数:核心线程数为手机CPU数量+1,最大线程数为手机CPU数量×2+1,线程队列的大小为128

4.利用submit去提交任务

submit和execute一样拥有提交任务的功能, 不同在于submit的提交拥有返回值。如下:

Future<?> submit(Runnable task);

<T> Future<T> submit(Runnable task, T result);

<T> Future<T> submit(Callable<T> task);

至于Future可以看看这些:

https://www.cnblogs.com/cz123/p/7693064.html

也就是说,我们的任务被转换成了Future,在异步执行的同时,我们还能取消这个任务的执行。看看下面代码:

public interface Future<V> { 
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

先看一个submit提交任务的demo:

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //ThreadPoolExecutor创建
        final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 1,
                TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
        //存储结果
        final List<Future<User>> futures = new ArrayList<>();

        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for (int i = 0; i < 10; i++) {
                    Future<User> taskFuture = threadPoolExecutor.submit(new MyTask(i));
                    //将每一个任务的执行结果保存起来
                    futures.add(taskFuture);
                }
                //查看结果
                try {
                    for (Future<User> future : futures) {
                        Log.d("姓名为:", future.get().getName());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    class User {
        private String name;
        public User(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }

    class MyTask implements Callable<User> {

        private int taskId;
        public MyTask(int taskId) {
            this.taskId = taskId;
        }
        @Override
        public User call() throws Exception {
            SystemClock.sleep(1000);
            //返回每一个任务的执行结果
            return new User(taskId + "");
        }
    }

5.自定义ThreadPoolExecutor

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final MyThreadPool myThreadPool = new MyThreadPool(3, 5, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>());
        findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                for (int i = 0; i < 10; i++) {
                    final int finalI = i;
                    Runnable runnable = new Runnable(){
                        @Override
                        public void run() {
                            SystemClock.sleep(100);
                            Log.d("MyThreadPool", "run: " + finalI);
                        }
                    };
                    myThreadPool.execute(runnable);
                }
            }
        });
    }

    class MyThreadPool extends ThreadPoolExecutor{

        //有4个构造方法可以选择
        public MyThreadPool(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }

        @Override
        protected void beforeExecute(Thread t, Runnable r) {
            super.beforeExecute(t, r);
            Log.d("MyThreadPool", "beforeExecute: 开始执行任务!");
        }

        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            Log.d("MyThreadPool", "beforeExecute: 任务执行结束!");
        }

        @Override
        protected void terminated() {
            super.terminated();
            //当调用shutDown()或者shutDownNow()时会触发该方法
            Log.d("MyThreadPool", "terminated: 线程池关闭!");
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_37321098/article/details/82784807