java Executors 线程池解读

来源:互联网 发布:ionic lab for mac 编辑:程序博客网 时间:2024/06/05 06:24

1.不变的java线程新建及启动方式

public class TestThread implements Runnable{

public void run(){

//out("hello..")

}

}

Thread thread = new Thread(TestThread);

thread.start();


2.Executors 以池的方式如何管理和启动线程?

以newFixedThreadPool方法为例,ExecutorService 具体对象为

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



参数含义及使用方式,代码如下:

if (workerCountOf(c) < corePoolSize) {            if (addWorker(command, true))                return;            c = ctl.get();        }        if (isRunning(c) && workQueue.offer(command)) {            int recheck = ctl.get();            if (! isRunning(recheck) && remove(command))                reject(command);            else if (workerCountOf(recheck) == 0)                addWorker(null, false);        }        else if (!addWorker(command, false))            reject(command);

解释:先用coreSize,满了后,用queue,queue再满,用maxSize,再满,那就reject


一般情况下ThreadFactory 以及 RejectedExecutionHandler 使用默认(也可自由实现)

默认ThreadFactory 如下:

   static class DefaultThreadFactory implements ThreadFactory {        private static final AtomicInteger poolNumber = new AtomicInteger(1);        private final ThreadGroup group;        private final AtomicInteger threadNumber = new AtomicInteger(1);        private final String namePrefix;        DefaultThreadFactory() {            SecurityManager s = System.getSecurityManager();            group = (s != null) ? s.getThreadGroup() :                                  Thread.currentThread().getThreadGroup();            namePrefix = "pool-" +                          poolNumber.getAndIncrement() +                         "-thread-";        }        public Thread newThread(Runnable r) {            Thread t = new Thread(group, r,                                  namePrefix + threadNumber.getAndIncrement(),                                  0);            if (t.isDaemon())                t.setDaemon(false);            if (t.getPriority() != Thread.NORM_PRIORITY)                t.setPriority(Thread.NORM_PRIORITY);            return t;        }    }

这里包括了线程名字的命名,以及线程池所用线程对象(new Thread)的创建。


3. submit 做了什么?

先看下这个类

public abstract class AbstractExecutorService implements ExecutorService
方法包括

public Future<?> submit(Runnable task) {        if (task == null) throw new NullPointerException();        RunnableFuture<Void> ftask = newTaskFor(task, null);        execute(ftask);        return ftask;    }
以及

public <T> Future<T> submit(Callable<T> task) {        if (task == null) throw new NullPointerException();        RunnableFuture<T> ftask = newTaskFor(task);        execute(ftask);        return ftask;    }

不管submit的是Runnable还是Callable,都会转化为FutureTask的对象

其中的两个重要字段

    /** The underlying callable; nulled out after running */    private Callable<V> callable;    /** The result to return or exception to throw from get() */    private Object outcome; // non-volatile, protected by state reads/writes

用callable存放submit的Runnable或者Callable

再看FutureTask实现的两个接口Runnable, Future

其中,run方法的实现如下:

try {                    result = c.call();                    ran = true;                } catch (Throwable ex) {                    result = null;                    ran = false;                    setException(ex);                }                if (ran)                    set(result);

重点是,调用了Callable中的call方法,以及set(result),把结果放入outcome中。通过FutureTask的get()操作,获得左后的outcome结果。


4.回过头来,看下线程是如何start()的

当小于池的coreSize时,在类ThreadPoolExecutor的方法addWorker(Runnable firstTask, boolean core)中,重点代码如下:

final Thread t = w.thread;            if (t != null) {                final ReentrantLock mainLock = this.mainLock;                mainLock.lock();                try {                    // Recheck while holding lock.                    // Back out on ThreadFactory failure or if                    // shut down before lock acquired.                    int rs = runStateOf(ctl.get());                    if (rs < SHUTDOWN ||                        (rs == SHUTDOWN && firstTask == null)) {                        if (t.isAlive()) // precheck that t is startable                            throw new IllegalThreadStateException();                        workers.add(w);                        int s = workers.size();                        if (s > largestPoolSize)                            largestPoolSize = s;                        workerAdded = true;                    }                } finally {                    mainLock.unlock();                }                if (workerAdded) {                    t.start();                    workerStarted = true;                }            }

其中,t 对象就是上面DefaultThreadFactory创建出来的线程,看后面的代码,执行了 t.start();

还有一处需要关注的是workers.add(w),这里就是池维护的线程集合,workers 是HastSet类型。


5.总结下

(1)DefaultThreadFactory用于创建真正执行的线程

(2)ThreadPoolExecutor用于维护池及队列、执行线程等

(3)FutureTask 是池中线程执行的最终任务(也就是实现Runnable的类),它还有另一个职责,就是存储、返回了  .get()的结果

(4)用户自己创建的TestThread ,不管是Runnable还是Callable,最终都被转为Callable,并在FutureTask 的run方法中执行了  .call() 方法



6.欢迎指正错误,我也会不断补充。




原创粉丝点击