Correct use of thread pools in Java

In the Java development manual released by Ali recently, it is mandatory that thread pools are not allowed to use Executors to create, but through ThreadPoolExecutor. This way of processing allows the students who write to be more specific about the running rules of the thread pool and avoid the risk of resource exhaustion.

Executors provide us with 4 thread pool implementations using the factory pattern, but it is not recommended because the use of Executors to create a thread pool will not pass in this parameter and use the default value, so we often ignore this parameter and use the default value. Parameters will lead to waste of resources, which is not desirable.

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize - The size of the thread pool core pool.
  • maximumPoolSize - The maximum number of threads in the thread pool.
  • keepAliveTime - When the number of threads is greater than the core, this is the maximum amount of time that excess idle threads wait for new tasks before terminating.
  • unit - the time unit for keepAliveTime.
  • workQueue - A queue used to store tasks waiting to be executed.
  • threadFactory - the thread factory.
  • handler - the rejection policy.

Specifically use the ThreadPollExecutor method:

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
				.setNameFormat("demo-pool-%d").build();
		ExecutorService threadPool = new ThreadPoolExecutor(4,
				20,
				1000L,
				TimeUnit.MILLISECONDS,
				new ArrayBlockingQueue<Runnable>(1024),
				namedThreadFactory,
				new ThreadPoolExecutor.AbortPolicy());

Precautions:

  1. We use ThreadFactoryBuilder provided by google to implement thread naming
  2. ThreadPoolExecutor.AbortPolicy() thread rejection policy

Thread rejection strategy, you need to implement RejectdExecutionHandler to override the rejectedExecution method

public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

Several rejection strategies provided by default by ThreadPollExecutor

/**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

    /**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325061443&siteId=291194637