Talk Interview Java thread pool

Background

About Java thread pool I think we certainly are no strangers in their usual work or study in more or less will be used, then you really have to find out about realization of the principles underlying it? Or just stop the stage with it? And regarding Java thread pool is a high frequency of face questions in the interview, just like the HashMap implementation principle is basically the interview will be asked have been asked to estimate bad streets.

Digression: The principle has been asked HashMap really rotten in my own many times do not know the interview was asked a few times, sometimes very strange to think about why this is a bad street asked questions it still has to be asked? But from the perspective of the interviewer to think about it, if a bad street are asked questions you do not properly prepare to treat it, how can it work properly treat (personal humble opinion).

Several common thread pool

Let's look at ways to create several common thread pool and the achievement of the principles underlying the use of

Single thread:  Executors.newSingleThreadExecutor () ;

public static ExecutorService newSingleThreadExecutor() {        return new FinalizableDelegatedExecutorService            (new ThreadPoolExecutor(1, 1,                                    0L, TimeUnit.MILLISECONDS,                                    new LinkedBlockingQueue<Runnable>()));    }

Cache thread: Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>());    }

Fixed threadExecutors.newFixedThreadPool(2);

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

Timing threads:  Executors.newScheduledThreadPool(3);(parent class)

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue) {        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,             Executors.defaultThreadFactory(), defaultHandler);    }

core ThreadPoolExecutor

Above the bottom of the thread pool is achieved by a few, we can see through the bottom is  ThreadPoolExecutor achieved class, but not the same parameters, it is necessary that we look at ThreadPoolExecutor this kind of

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler) {        if (corePoolSize < 0 ||            maximumPoolSize <= 0 ||            maximumPoolSize < corePoolSize ||            keepAliveTime < 0)            throw new IllegalArgumentException();        if (workQueue == null || threadFactory == null || handler == null)            throw new NullPointerException();        this.corePoolSize = corePoolSize;        this.maximumPoolSize = maximumPoolSize;        this.workQueue = workQueue;        this.keepAliveTime = unit.toNanos(keepAliveTime);        this.threadFactory = threadFactory;        this.handler = handler;    }

By JDK source code, we can see  ThreadPoolExecutor in the concurrent Java packages below, and there are four construction method, introduced in turn below under the meaning of the various parameters:

• corePoolSize: the number of kernel threads size • maximumPoolSize: maximum number of threads in the thread pool allowed • keepAliveTime: maximum idle threads allow the survival time • unit: the survival time of the unit • workQueue: blocked task queue • threadFactory: a thread factory used to create a thread • handler: refuse strategies for handling when the queue is full of new tasks

Through the above analysis parameters, we can know that a single thread is a thread pool thread pool thread is responsible for only one task, so the values ​​are corePoolSize and maximumPoolSize 1; when this thread is any irregularity, the thread pool will automatically create a thread, there is always a thread pool thread and only one survived. And the other thread pool just set the parameters just not the same. We also need to know a few common relational thread pool classes and interfaces, as well as some ways, as shown below

ThreadPoolExecutor Inheritance  AbstractExecutorService; AbstractExecutorService realization  ExecutorServiceExecutorService inheritance Executor

Source code analysis

The source can be found throughout the thread pool is roughly divided into three parts, a worker thread is created, to add the task 2 workQueue;.. 3.worker threads perform specific tasks

Create a worker thread, and now we look at the core of the  execute(Runnable command) method, if the worker is less than the specified number of kernel threads will try to create a new thread,

public void execute(Runnable command) {    if (command == null)        throw new NullPointerException();    int c = ctl.get();    //如果工作线程比核心线程数少,则创建新线程    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);}

Look at addWorker(Runnable firstTask, boolean core) Methods

private boolean addWorker(Runnable firstTask, boolean core) {    retry:    for (;;) {        int c = ctl.get();        int rs = runStateOf(c);        if (rs >= SHUTDOWN &&            ! (rs == SHUTDOWN &&               firstTask == null &&               ! workQueue.isEmpty()))            return false;        for (;;) {            int wc = workerCountOf(c);            if (wc >= CAPACITY ||                wc >= (core ? corePoolSize : maximumPoolSize))                return false;            if (compareAndIncrementWorkerCount(c))                break retry;            c = ctl.get();  // Re-read ctl            if (runStateOf(c) != rs)                continue retry;        }    }    boolean workerStarted = false;    boolean workerAdded = false;    Worker w = null;    try {        w = new Worker(firstTask);        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;            }        }    } finally {        if (! workerStarted)            addWorkerFailed(w);    }    return workerStarted;}

Add tasks to workQueue, this method of blocking queue inside

public boolean offer(E e) {    if (e == null) throw new NullPointerException();    final AtomicInteger count = this.count;    if (count.get() == capacity)        return false;    int c = -1;    Node<E> node = new Node<E>(e);    final ReentrantLock putLock = this.putLock;    putLock.lock();    try {        if (count.get() < capacity) {            enqueue(node);            c = count.getAndIncrement();            if (c + 1 < capacity)                notFull.signal();        }    } finally {        putLock.unlock();    }    if (c == 0)        signalNotEmpty();    return c >= 0;}

worker thread to perform specific tasks, or blocking timeout to get jobs in the queue, execution

final void runWorker(Worker w) {    Thread wt = Thread.currentThread();    Runnable task = w.firstTask;    w.firstTask = null;    w.unlock(); // allow interrupts    boolean completedAbruptly = true;    try {        //阻塞循环获取任务        while (task != null || (task = getTask()) != null) {            w.lock();            if ((runStateAtLeast(ctl.get(), STOP) ||                 (Thread.interrupted() &&                  runStateAtLeast(ctl.get(), STOP))) &&                !wt.isInterrupted())                wt.interrupt();            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);    }}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;        }        int wc = workerCountOf(c);        // Are workers subject to culling?        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;        if ((wc > maximumPoolSize || (timed && timedOut))            && (wc > 1 || workQueue.isEmpty())) {            if (compareAndDecrementWorkerCount(c))                return null;            continue;        }        try {            Runnable r = timed ?                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :                workQueue.take();            if (r != null)                return r;            timedOut = true;        } catch (InterruptedException retry) {            timedOut = false;        }    }}

When just create a thread pool, the number of internal threads is 0, when the first task added, would be to create a thread according to the configuration parameters, and with the increasing number of tasks, will gradually create a new thread until I can not create a new thread so far. After not create a new thread will be stored for future mission to the blocking queue, so that the idle thread to handle. When there is no idle threads and the queue is full when it will refuse to adopt strategies to discard or other strategies to deal with. There are four main strategies denial, denial different strategies have different usage scenarios, we need to decide according to the situation.

CallerRunsPolicy : the calling thread processing tasks • AbortPolicy : throw an exception • DiscardPolicy : discards • DiscardOldestPolicy : discard the oldest task queue, to perform new tasks

summary

The thread pool using essential work, how elegant use the thread pool can improve performance and efficiency in large degree. According to the actual application scenarios, configure the appropriate thread pool can improve performance parameters big project, you can also take advantage of the server's performance.

 


 


 

Java technology geeks public number, is founded by a group of people who love Java technology development, focused on sharing of original, high-quality Java articles. If you feel that our article is not bad, please help appreciated, watching, forwarding support, encourage us to share a better article.

No public concern, we can reply, "blog Park" No background in public, freely available knowledge of Java / information interview must-see.

 

Guess you like

Origin www.cnblogs.com/justdojava/p/11211732.html