前进吧蜗牛程序员Java学习笔记

java 线程池使用和详解

2017-06-08  本文已影响549人  cobs

线程池的使用

构造方法

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

注意

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();


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

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


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

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

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

前进吧蜗牛
上一篇 下一篇

猜你喜欢

热点阅读