java 线程池使用和详解

线程池的使用

构造方法

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize:线程池维护线程的最少数量
  • maximumPoolSize:线程池维护线程的最大数量
  • keepAliveTime:线程池维护线程所允许的空闲时间
  • unit:线程池维护线程所信息的空闲时间的单位
  • workQueue:线程池所使用的缓冲队列
  • threadFactory:线程创建工厂类
  • handler:线程池对任务的处理策略

注意

  • 线程池在创建的时候是不创建线程的,只有加入任务才创建线程,当然可以调用prestartCoreThread方法(是在ThreadPoolExecutor类中实现的)来初始化一个线程。
  • 线程池先会创建完corePoolSize个线程,在把任务保存到队列中,队列满后才会再创建线程,直到规定的maximumPoolSize,然后会执行拒绝策略。
  • 设置线程池的大小参考
    • 如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1
    • 如果是IO密集型任务,参考值可以设置为2*NCPU

BlockingQueue常用的3个实现类

  1. ArrayBlockingQueue 构造参数必须带一个int参数来指明其大小,FIFO
  2. LinkedBlockingQuene 大小不定,可以人为指定,若没有有Integer.MAX_VALUE来决定。FIFO
  3. SynchronousQueue 对其操作必须放和取交替完成。在线程池中它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务

LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue.
SynchronousQueue初始化后必须先有其他线程对其使用take()方法后才能使用put() 或者 offer()方法

java 定义好的4中类型的线程池

  1. newCachedThreadPool创建一个可缓冲线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可用线程,则新建线程
  2. newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadPool 创建一个定长线程池,支持定时和周期性任务执行。
  4. newSingleThreadExecutor 一个单线程化的线程池,确保所有任务按照指定的顺序执行。

下面是线程池核心的执行代码,只看懂一点:cry:

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        //它在执行完一个线程会getTask再去取一个,直到没有任务。
        while (task != null || (task = getTask()) != null) {
            w.lock();
            //.......删除N行代码
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

gettask方法

private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            //......省略N行代码

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

这里用到了BlockingQueue的方法,很巧妙的使用。timed是判断这个线程是否可以回收,由我们设置的allowCoreThreadTimeOut和当前线程池线程大小决定的。当要回收,用的是poll方法,不能回收用的是take方法阻塞线程

线程池的shutdown()和shutdownNow();

  • shutdown()方法会更改线程池的状态为SHUTDOWN状态,并不会立即终止。此时不能往线程池中添加任务,否则会抛出RejectedExecutionException异常。它会等线程池里的所有任务都处理完毕再退出线程。
  • shutdownNow()方法会立即更改状态为STOP状态。并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,它会返回那些未执行的任务。其试图终止线程的方法是通过调用Thread.interrupt()方法来实现的。

提个问题,线程池有两种提交方式execute()和submit()区别,可以在评论区讨论哦!请关注微信公众号,查看,嘻嘻。不过以后会在评论区回复的!!

如果大家感觉满意,就点个喜欢吧!!哈哈


上一篇文章 java 线程和线程安全初识

如有什么不对的地方,欢迎大家指出来,我们共同学习!!
接下来会写关于 内部类 的文章,谢谢大家关注

欢迎关注我的微信公众号cobs-snail,让我们一起前进吧!!

java 线程池使用和详解_第1张图片
前进吧蜗牛

你可能感兴趣的:(java 线程池使用和详解)