Java Concurrency series of four: a custom thread pool denial policy

introduction

ThreadPoolExcutorA JDKbuilt-in thread pool, but also we often use the method to create when you create a thread pool. Thread pool a little understanding of the students know, the thread pool is a typical pool of cache design. JDKComes with four tasks deny policy, but sometimes we can not meet the real business needs, so in this case we need to customize the policy to refuse to deal with the rejected task thread pool.

  • Thread Pool comes deny policy introduced
  • How to customize deny policy

First, comes the thread pool rejection policy introduced

JDK comes with the thread pool denial strategy has the following four categories:

1, DiscardPolicy: silently discard task can not be processed without any treatment;

public static class DiscardPolicy implements RejectedExecutionHandler {
	public DiscardPolicy() { }
	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
}

2, DiscardOldestPolicy : discard the oldest task in the queue, try to submit the current job again;

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
	public DiscardOldestPolicy() { }
	
	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
	
}

3, AbortPolicy : direct throw an exception that prevents the system is working properly;

public static class AbortPolicy implements RejectedExecutionHandler {
	public AbortPolicy() { }

	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }

}

4, CallerRunsPolicy : will be divided to the calling thread to perform the task, run the task currently being discarded, so do not really discard task, but the thread performance is likely to submit a sharp decline

public static class CallerRunsPolicy implements RejectedExecutionHandler {
	public CallerRunsPolicy() { }

	public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
}

We can see that the first three strategies are discards the original task. However, in some business scenarios, we can not discard the brutal task. A fourth refused strategy is to deal with discarded task by starting a thread pool thread, but the problem is that even the thread pool idle, it will not perform tasks discarded, but wait for the main thread calls the thread pool to perform the task, until the end of the mission.

Second, comes the thread pool rejection policy introduced

In the definition of the thread pool, we can see that there is a unified policy to refuse to implement the interface, as follows:

public interface RejectedExecutionHandler {
	 void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

We can define processing strategy in line with their own business scenarios according to their business needs. We can look at some of the mainstream framework is how to define your own self-processing strategy.

1, Netty threads in the pool rejection policy

 private static final class NewThreadRunsPolicy implements RejectedExecutionHandler {
        NewThreadRunsPolicy() {
            super();
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                final Thread t = new Thread(r, "Temporary task executor");
                t.start();
            } catch (Throwable e) {
                throw new RejectedExecutionException(
                        "Failed to start a new thread", e);
            }
        }
    }

Source can be seen from the above, Nettythe task of handling is not discarded, and this idea CallerRunsPolicysimilar advantages. In just Nettya custom frame reject strategy is to complete the task of discarded thread through the new work, but we come to look at it in a thread is created, no constraint conditions, as long as resources allow to continue to create new thread for processing.

2, Dubbo threads in the pool rejection policy

public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {

    protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);

    private final String threadName;

    private final URL url;

    private static volatile long lastPrintTime = 0;

    private static Semaphore guard = new Semaphore(1);

    public AbortPolicyWithReport(String threadName, URL url) {
        this.threadName = threadName;
        this.url = url;
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        String msg = String.format("Thread pool is EXHAUSTED!" +
                        " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
                        " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!",
                threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
                e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
                url.getProtocol(), url.getIp(), url.getPort());
        logger.warn(msg);
        dumpJStack();
        throw new RejectedExecutionException(msg);
    }

    private void dumpJStack() {
       //省略实现
    }
}

DubboCustom refused strategy, print the log output current thread stack information and perform JDKa default deny policy.

Published 88 original articles · won praise 49 · Views 100,000 +

Guess you like

Origin blog.csdn.net/Diamond_Tao/article/details/100183424