This article is roughly divided into 10 parts, which are

1. Thread pool workflow

2. Thread pool constructor

3. Thread pool parameters

4. Use the thread pool example

5. What is a thread factory

6. What is the rejection strategy

7. Common blocking queues

8. Common thread pool usage

9. Extend the thread pool method

10. Digression

We know that creating a thread and destroying a thread in a computer are both very resource-intensive operations, and there’s an idea called pooling, which means we create a pool, we do all the resource-intensive operations ahead of time, and then we all use what we’ve created together, and then we destroy it. Save the use of a create a, destroy a, this resource – consuming operation.

I. How thread pools work

This is the idea of a thread pool, whose basic workflow is shown in the figure below

The following figure shows the basic thread pool workflow

So what are his core threads, his task queues, these? How do you set it?

We’ll start with the code. Let’s first look at the thread pool constructor code

Thread pool constructor

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.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}
Copy the code

There are actually four constructors for ThreadPoolExecutor, but the bottom line is the seven-argument constructor, so it’s good to understand this one. Here’s the bottom line implementation of the other constructors

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
Copy the code
   public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
Copy the code
  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

Copy the code

The default rejection policy is

private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

Copy the code

Of these constructors

        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
Copy the code

That’s the constructor for those seven parameters

Mentally? It doesn’t matter. Let’s analyze each of the seven parameters one by one

3. Thread pool parameters

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.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}
Copy the code

1. The first parameter corePoolSize represents the number of core threads in the thread pool

2. The second parameter, maximumPoolSize, represents the maximum number of threads in the pool (core + non-core).

3. The third parameter, keepAliveTime, represents the idle lifetime of the pool’s non-core threads

4. The fourth argument, unit, represents the unit of idle lifetime for the non-core threads of the thread pool

5. The fifth parameter workQueue represents the task blocking queue for this thread pool. There are several common blocking queues in the JDK

  • ArrayBlockingQueue: Bounded blocking queue based on array structure
  • LinkedBlockingQueue: Is a blocking queue based on a linked list structure
  • SynchronousQueue: a SynchronousQueue that stores only one task and waits to insert it (if there are elements in the queue) and to retrieve it (if there are no elements)
  • PriorityBlockingQueue: Priority queue. Elements entering the queue are sorted in order of priority

Suggestion: It is recommended to use a bounded queue. If there are too many tasks in an unbounded queue, it may cause an OOM result

6. The sixth argument, threadFactory (customizable), represents the factory that creates threads for the pool. There are two types of factory

  • Executors. PrivilegedThreadFactory () to use access to create a thread of access control.
  • Executors. DefaultThreadFactory () will create a thread group and the default priority threads

7. The seventh parameter, handler (which can be customized), represents the saturation policy for the thread pool to deny processing tasks. The JDK provides four by default

  • new ThreadPoolExecutor.AbortPolicy(); Direct throw exception
  • new ThreadPoolExecutor.CallerRunsPolicy(); Process the passed task in the current caller’s thread
  • new ThreadPoolExecutor.DiscardOldestPolicy(); Discard the oldest task and add the incoming task to the blocking queue
  • new ThreadPoolExecutor.DiscardPolicy(); Do nothing, just throw away the task that was handed to you

Use thread pool example

With the basic concepts covered, let’s look at a small example of using thread pools to process tasks

First, let’s create a task class

public class Task implements Runnable {
    private String taskName;
    
    public Task(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public void run(a) {
        try {
            // Simulate the time spent for each task
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String name = Thread.currentThread().getName();
        System.out.println("This is xhJaver, the current thread name of the thread pool series is" + name+"Dealt with"+ taskName+"  任务"); }}Copy the code

Let’s look at the test class again

public class Demo1 {
    public static void main(String[] args) {
        // Block the queue and set the maximum number of blocked tasks to 10
        BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable> (10);
        // Thread factory
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        When the maximum worker of the thread pool is full and the blocking queue is full, the reject policy handles the rest of the work
        ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();
        // Create a thread pool. The number of core threads is 5. The maximum number of threads is 10
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5.10.60L,
                        TimeUnit.SECONDS, blockingQueue, threadFactory, abortPolicy
        );
        for (int i=0; i<10; i++){// Create 10 tasks. If >20 tasks are created, all tasks outside 20 will be handled by the denial policy
            Task task = new Task("task" + i);
            // Let's create our own thread pool to run these tasks
            threadPoolExecutor.execute(task);
        }
         // Remember to close the thread poolthreadPoolExecutor.shutdown(); }}Copy the code

The output is

Here is xhJaver, the thread pool series current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-2This is xhJaver. The current thread name of the thread pool series is pool-1-thread-3This is xhJaver. The current thread name of the thread pool series is pool-1-thread-4This is xhJaver. The current thread name of the thread pool series is pool-1-thread-5This is xhJaver. The current thread name of the thread pool series is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-2This is xhJaver, thread pool series. The current thread name is pool-1-thread-5This is xhJaver, thread pool series. The current thread name is pool-1-thread-4This is xhJaver, thread pool series. The current thread name is pool-1-thread-3The Task7 task is processedCopy the code

What is a thread factory?

Thread factory thread factory, what is a thread factory? The factory that creates the thread must have a name, as shown in the example above. The name of the thread is pool-1-thread-3 and so on.

First, you implement the Thread newThread(Runnable r) method in the ThreadFactory interface, passing in a task that returns a custom Thread, as shown below

public class DIYThreadFactory implements ThreadFactory {

    private AtomicInteger atomicInteger;

    public  DIYThreadFactory( AtomicInteger atomicInteger){
         this.atomicInteger =  atomicInteger;
    }
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setName("xhJaver-thread-"+atomicInteger.getAndIncrement());
        returnthread; }}Copy the code

This custom thread factory is then passed in when used

public static void main(String[] args) {
	// Block the queue and set the maximum number of blocked tasks to 10
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable> (10);
	// Create a thread-safe counter
	AtomicInteger atomicInteger = new AtomicInteger();
	// Custom thread factory
	ThreadFactory threadFactory = new DIYThreadFactory(atomicInteger);
	When the maximum worker of the thread pool is full and the blocking queue is full, the reject policy handles the rest of the work
ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();
	// Create a thread pool. The number of core threads is 5. The maximum number of threads is 10
	ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5.10.60L,
			TimeUnit.SECONDS, blockingQueue, threadFactory, abortPolicy
	);
	for (int i=0; i<10; i++){// Create 10 tasks. If >20 tasks are created, all tasks outside 20 will be handled by the denial policy
		Task task = new Task("task" + i);
		// Let's create our own thread pool to run these tasks
		threadPoolExecutor.execute(task);
	}
	// Remember to close the thread pool
	threadPoolExecutor.shutdown();
}
Copy the code

The output is

Here is xhJaver, the current thread name of the thread pool series is xhJaver-thread-0The current thread name of the thread pool series is xhJaver-thread-1The current thread name of the thread pool series is xhJaver-thread-4The current thread name of the thread pool series is xhJaver-thread-3The current thread name of the thread pool series is xhJaver-thread-2The current thread name of the thread pool series is xhJaver-thread-0This is xhJaver, and the current thread name of the thread pool series is xhJaver-thread-1The current thread name of the thread pool series is xhJaver-thread-2The current thread name of the thread pool series is xhJaver-thread-3The current thread name of the thread pool series is xhJaver-thread-4The Task7 task is processedCopy the code

I also learned to customize the thread factory, but the custom name is useful, of course, to troubleshoot problems! Define the thread name as the name related to your business, when the error will be convenient troubleshooting.

What is the rejection strategy

Thread factories can be customized, but can rejection policies be customized? RejectedExecutionHandler (); rejectedExecution ()

public class DIYRejectedHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    // Record operations such as logs
        System.out.println("This is a task that xhJaver cannot handle."+r.toString()+"Current thread name is"+Thread.currentThread().getName()); }}Copy the code

This custom rejection policy is then passed in when used

public static void main(String[] args) {
	// Block the queue and set the maximum number of blocked tasks to 10
	BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable> (10);
	// Create a thread-safe counter
	AtomicInteger atomicInteger = new AtomicInteger();
	// Custom thread factory
	ThreadFactory threadFactory = new DIYThreadFactory(atomicInteger);
	When the maximum worker thread in the thread pool is full and the blocking queue is full, the reject policy handles the rest of the work
	DIYRejectedHandler diyRejectedHandler = new DIYRejectedHandler();
	// Create a thread pool. The number of core threads is 5. The maximum number of threads is 10
	ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5.10.60L,
			TimeUnit.SECONDS, blockingQueue, threadFactory, diyRejectedHandler
	);
	for (int i=0; i<30; i++){// Create 10 tasks. If >20 tasks are created, all tasks outside 20 will be handled by the denial policy
		Task task = new Task("task" + i);
		// Let's create our own thread pool to run these tasks
		threadPoolExecutor.execute(task);
	}
	// Remember to close the thread pool
	threadPoolExecutor.shutdown();
}
Copy the code

The output is

This is a Task that xhJaver cannot handle Task{taskName='task20'} The current thread name is main. This is a Task that xhJaver cannot handle'task21'} The current thread name is main. This is a Task that xhJaver cannot handle'task22'} The current thread name is main. This is a Task that xhJaver cannot handle'task23'} The current thread name is main. This is a Task that xhJaver cannot handle'task24'} The current thread name is main. This is a Task that xhJaver cannot handle'task25'} The current thread name is main. This is a Task that xhJaver cannot handle'task26'} The current thread name is main. This is a Task that xhJaver cannot handle'task27'} The current thread name is main. This is a Task that xhJaver cannot handle'task28'} The current thread name is main. This is a Task that xhJaver cannot handle'task29'} The current thread name is xhJaver, and the current thread name is xhJaver-thread-5The current thread name of the thread pool series is xhJaver-thread-4The current thread name of the thread pool series is xhJaver-thread-3The current thread name of the thread pool series is xhJaver-thread-2The current thread name of the thread pool series is xhJaver-thread-1The current thread name of the thread pool series is xhJaver-thread-0The current thread name of the thread pool series is xhJaver-thread-9The current thread name of the thread pool series is xhJaver-thread-8The current thread name of the thread pool series is xhJaver-thread-7The current thread name of the thread pool series is xhJaver-thread-6The current thread name of the thread pool series is xhJaver-thread-4The current thread name of the thread pool series is xhJaver-thread-5This is xhJaver, and the current thread name of the thread pool series is xhJaver-thread-3The current thread name of the thread pool series is xhJaver-thread-2The current thread name of the thread pool series is xhJaver-thread-1The current thread name of the thread pool series is xhJaver-thread-0The current thread name of the thread pool series is xhJaver-thread-9The current thread name of the thread pool series is xhJaver-thread-8The current thread name of the thread pool series is xhJaver-thread-7The current thread name of the thread pool series is xhJaver-thread-6The TASK14 task is processedCopy the code

Common blocking queues and attention points

Because there’s a lot to know about blocking queues, we’ll start with blocking queues in its own right, starting with a few common ones

LinkedBlockingQueue is an unbounded queue based on a linked list. It has only one element inside. It blocks if an element is not removed from the queue. Fetching an element is blocked if there are no elements in the queue until an element is inserted.

To match the thread pool use the following, first create the task class

public class Task implements Runnable {
    private String taskName;

    public Task(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public String toString(a) {
        return "Task{" +
                "taskName='" + taskName + '\' ' +
                '} ';
    }

    @Override
    public void run(a) {
        try {
            // Simulate the time spent for each task
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String name = Thread.currentThread().getName();
        System.out.println("This is xhJaver, the current thread name of the thread pool series is" + name+"Dealt with"+ taskName+"  任务"); }}Copy the code

Then use the blocking queue

public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i=0; i<10; i++){// Create ten tasks
            Task task = new Task("task" + i);
            // Go on a mission
            executorService.execute(task);
        }
         // Remember to close the thread pool
        executorService.shutdown();
    }
Copy the code

The underlying use of newCachedThreadPool is SynchronousQueue

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

The output is

Here is xhJaver, the thread pool series current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-2This is xhJaver. The current thread name of the thread pool series is pool-1-thread-5This is xhJaver. The current thread name of the thread pool series is pool-1-thread-4This is xhJaver. The current thread name of the thread pool series is pool-1-thread-3This is xhJaver. The current thread name of the thread pool series is pool-1-thread-6This is xhJaver, thread pool series. The current thread name is pool-1-thread-7This is xhJaver, thread pool series. The current thread name is pool-1-thread-10This is xhJaver, thread pool series. The current thread name is pool-1-thread-9This is xhJaver, thread pool series. The current thread name is pool-1-thread-8The Task7 task is processedCopy the code

As you can see, the thread pool creates ten threads to handle each of these ten tasks. Why? This is because, I simulate the processing time of each task is 1 s, when the task has found that blocking the queue again task has not been removed, is just to create non-core thread to handle this task, constantly to task, constantly create threads, so blocking queue with this match again thread pool set parameters, such as the total number of threads may lead to OOM for continuously create a thread.

Elements entering the queue are sorted by task priority. And the Comparable interface must be implemented.

Parameter: priorityTask – The object to be compared. Returns: a negative integer, zero, or positive integer depending on whether the object is less than, equal to, or greater than the specified object (the object to be compared).

Start by creating a task with a priority

public class PriorityTask implements Runnable , Comparable<PriorityTask>{

    private String taskName;
    // Priority, which is sorted by this number
    private Integer priority;

    public PriorityTask(Integer priority,String taskName) {
        this.priority = priority;
        this.taskName = taskName;
    }
    
    // If the return value of the compareTo method is -1, the order will consider that the passed task is larger than this task and will be sorted in descending order
    // If the return value of the compareTo method is 1, the order will consider that the passed task is smaller than this task, and the order will be ascending
    @Override
    public int compareTo(PriorityTask priorityTask) {
        //Integer.compare returns -1 to indicate that the priority of the passed task is smaller than the priority of the secondary task
        // Integer.compare 0 the priority of the passed task is the same as the priority of the secondary task
        //Integer.compare 1: the priority of the passed task is greater than the priority of the secondary task
        return Integer.compare(priorityTask.priority,this.priority);
    }

    @Override
    public void run(a) {
        try {
            // Simulate the time spent for each task
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String name = Thread.currentThread().getName();
        System.out.println("This is xhJaver, the current thread name of the thread pool series is" + name+"Dealt with"+ taskName+"  任务");
    }

    @Override
    public String toString(a) {
        return "Task{" +
                "taskName='" + taskName + '\' ' +
                '} '; }}Copy the code

Comparison size code for Integer.compare

java
   public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
Copy the code

The test code


  public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1.1.60L, TimeUnit.SECONDS,
                new PriorityBlockingQueue());
        for (int i=0; i<5; i++){// Create ten tasks
            PriorityTask priorityTask = new PriorityTask(i,"task" + i);
            // Go on a mission
            threadPoolExecutor.execute(priorityTask);
        }
        for (int i=100; i>=95; i--){// Create ten tasks
            PriorityTask priorityTask = new PriorityTask(i,"task" + i);
            // Go on a mission
            threadPoolExecutor.execute(priorityTask);
        }
         // Remember to close the thread pool
        threadPoolExecutor.shutdown();
    }
Copy the code

The output is

Here is xhJaver, the thread pool series current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver, thread pool series. The current thread name is pool-1-thread-1This is xhJaver. The current thread name of the thread pool series is pool-1-thread-1This is xhJaver. The current thread name of the thread pool series is pool-1-thread-1This is xhJaver. The current thread name of the thread pool series is pool-1-thread-1The task1 task is processedCopy the code

As you can see from the output, with the exception of the first one, the order of processing tasks is first processed according to the priority size

Eight, several common thread pools and points to note

They are the following

1.newFixedThreadPool

  • Executors. NewFixedThreadPool (10) is its construction method
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
Copy the code

So, this FixedThreadPool has the same number of core threads as the maximum number of threads, so there are no non-core threads, and the lifetime parameter is invalid. It uses LinkedBlockingQueue, which is an unbounded queue. You can click on the source code to see that its default capacity is integer.max_value

 public LinkedBlockingQueue(a) {
        this(Integer.MAX_VALUE);
    }
Copy the code

So what’s the problem with that? When the core threads are full, new tasks will be added to the blocking queue, but the memory is limited, so there may be OOM (OutOfMemory) issues

  • Executors.newFixedThreadPool(10,Executors.defaultThreadFactory());

This constructor can be passed to the specified factory that created the thread

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

2.newCachedThreadPool

  • Executors.newCachedThreadPool()

The way it’s constructed is

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

The default number of core threads is 0, the total thread size of the pool is Integer.MAX_VALUE, the blocking queue is SynchronousQueue, and the idle lifetime of non-core threads is 60 seconds. If a task is created, a non-core thread will be created to run the task. If another task is created while the task is running, a thread will be created to run the task

  • Executors.newCachedThreadPool(Executors.defaultThreadFactory())

This constructor can be passed to the specified factory that created the thread

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

3.newSingleThreadExecutor

  • Executors.newSingleThreadExecutor()

The way it’s constructed is

public static ExecutorService newSingleThreadExecutor(a) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1.1.0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
Copy the code

We can see that it has one core thread and one total thread. If there are no threads in the thread pool, a single thread will be created to execute the task. The rest of the tasks will be put into the unbounded blocking queue. This will also cause an OOM issue.

  • Executors.newSingleThreadExecutor(Executors.defaultThreadFactory())

This constructor can be passed to the specified factory that created the thread

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1.1.0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
Copy the code

Expand the thread pool

What? Can thread pools be expanded? ! ThreadPoolExecutor provides several methods inside the ThreadPoolExecutor function, including beforeExecute, afterExecute, and terminated methods. These three situations correspond to task start, task end, and thread pool closed, so we need to rewrite them. Without further comment, let’s look at the code

public static void main(String[] args) {
	// Block the queue and set the maximum number of blocked tasks to 10
	BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable> (10);
	// Create a thread-safe counter
	AtomicInteger atomicInteger = new AtomicInteger();
	// Custom thread factory
	ThreadFactory threadFactory = new DIYThreadFactory(atomicInteger);
	When the maximum worker thread in the thread pool is full and the blocking queue is full, the reject policy handles the rest of the work
	DIYRejectedHandler diyRejectedHandler = new DIYRejectedHandler();
	// Create a thread pool. The number of core threads is 5. The maximum number of threads is 10
	ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5.10.60L,
			TimeUnit.SECONDS, blockingQueue, threadFactory, diyRejectedHandler
	){
		@Override
		protected void beforeExecute(Thread t, Runnable r) {
			System.out.println("The current thread of xhJaver is"+t.getName()+"Get started on a task:"+r.toString());
		}

		@Override
		protected void afterExecute(Runnable r, Throwable t) {
			if(t! =null){
				System.out.println("The current thread of xhJaver is"+Thread.currentThread().getName() +"End of processing task:"+r.toString()+"The mistake is"+ t);
			}
			System.out.println("The current thread of xhJaver is"+Thread.currentThread().getName() +"End of processing task:"+r.toString()+"There is no error.");

		}

		@Override
		protected void terminated(a) {
			System.out.println("The current thread of xhJaver is"+Thread.currentThread().getName() +"Close the thread pool"); }};for (int i=0; i<21; i++){// Create 10 tasks. If >20 tasks are created, all tasks outside 20 will be handled by the denial policy
		Task task = new Task("task" + i);
		// Let's create our own thread pool to run these tasks
		threadPoolExecutor.execute(task);
	}
	// Remember to close the thread pool
	threadPoolExecutor.shutdown();
}
Copy the code

The output is

This is a Task that xhJaver cannot handle Task{taskName='task20'} The current thread name is main xhJaver. The current thread name is xhJaver-thread-7To start a Task: Task{taskName='task17'} xhJaver The current thread is xhJaver thread-6To start a Task: Task{taskName='task16'} xhJaver The current thread is xhJaver thread-9To start a Task: Task{taskName='task19'} xhJaver The current thread is xhJaver thread-4To start a Task: Task{taskName='task4'} xhJaver The current thread is xhJaver thread-8To start a Task: Task{taskName='task18'} xhJaver The current thread is xhJaver thread-2To start a Task: Task{taskName='task2'} xhJaver The current thread is xhJaver thread-3To start a Task: Task{taskName='task3'} xhJaver The current thread is xhJaver thread-5To start a Task: Task{taskName='task15'} xhJaver The current thread is xhJaver thread-0To start a Task: Task{taskName='task0'} xhJaver The current thread is xhJaver thread-1To start a Task: Task{taskName='task1'} xhJaver, thread pool series current thread name xhJaver-thread-4The current thread xhJaver is xhJaver thread-4Task handling is complete: Task{taskName='task4'} No error xhJaver the current thread is xhJaver thread-4To start a Task: Task{taskName='task5'} xhJaver, thread pool series current thread name xhJaver-thread-9The current thread xhJaver is xhJaver thread-9Task handling is complete: Task{taskName='task19'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-6The current thread is xhJaver-thread-6Task handling is complete: Task{taskName='task16'} No error xhJaver the current thread is xhJaver thread-9To start a Task: Task{taskName='task6'} xhJaver, thread pool series current thread name xhJaver-thread-7The current thread is xhJaver-thread-7Task handling is complete: Task{taskName='task17'} No error xhJaver the current thread is xhJaver thread-7To start a Task: Task{taskName='task8'} xhJaver The current thread is xhJaver thread-6To start a Task: Task{taskName='task7'} xhJaver, thread pool series current thread name xhJaver-thread-1The current thread name of the thread pool series is xhJaver-thread-8The current thread is xhJaver-thread-8Task handling is complete: Task{taskName='task18'} No error xhJaver the current thread is xhJaver thread-8To start a Task: Task{taskName='task9'} xhJaver, thread pool series current thread name xhJaver-thread-2The current thread is xhJaver-thread-2Task handling is complete: Task{taskName='task2'} No error xhJaver the current thread is xhJaver thread-2To start a Task: Task{taskName='task10'} xhJaver, thread pool series current thread name xhJaver-thread-3The current thread xhJaver is xhJaver-thread-3Task handling is complete: Task{taskName='task3'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-5The current thread xhJaver is xhJaver thread-5Task handling is complete: Task{taskName='task15'} No error xhJaver the current thread is xhJaver thread-5To start a Task: Task{taskName='task12'} xhJaver The current thread is xhJaver thread-1Task handling is complete: Task{taskName='task1'} No error xhJaver the current thread is xhJaver thread-1To start a Task: Task{taskName='task13'} xhJaver, thread pool series current thread name xhJaver-thread-0The current thread xhJaver is xhJaver thread-3To start a Task: Task{taskName='task11'} xhJaver The current thread is xhJaver thread-0Task handling is complete: Task{taskName='task0'} No error xhJaver the current thread is xhJaver thread-0To start a Task: Task{taskName='task14'} xhJaver, thread pool series current thread name xhJaver-thread-4The current thread is xhJaver-thread-4Task handling is complete: Task{taskName='task5'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-6The current thread is xhJaver-thread-6Task handling is complete: Task{taskName='task7'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-9The current thread xhJaver is xhJaver-thread-9Task handling is complete: Task{taskName='task6'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-7The current thread xhJaver is xhJaver thread-7Task handling is complete: Task{taskName='task8'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-2The current thread xhJaver is xhJaver thread-2Task handling is complete: Task{taskName='task10'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-8The current thread xhJaver is xhJaver thread-8Task handling is complete: Task{taskName='task9'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-5The current thread is xhJaver-thread-5Task handling is complete: Task{taskName='task12'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-0The current thread xhJaver is xhJaver thread-0Task handling is complete: Task{taskName='task14'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-3The current thread is xhJaver-thread-3Task handling is complete: Task{taskName='task11'} no error here is xhJaver, thread pool series current thread name is xhJaver-thread-1The current thread xhJaver is xhJaver-thread-1Task handling is complete: Task{taskName='task13'} No error xhJaver the current thread is xhJaver thread-1Closing a thread poolCopy the code

These are some of the basic uses of thread pools. The next xhJaver article will look at some thread pools in action to reinforce these ideas.

Ten, digression

XhJaver finally decided to become a blogger (the public account is also this yo), if there is any mistake in this article, please point out, I also continue to learn and grow, thank you for your correction. Jingdong probation obtainment and turned away, taking the process and everything is moving in the right direction, and I also love to which Jony – j in the “players” in the lyrics, here for you “I don’t like DaZui cannons, shout slogans, to conform the drain, want the boat I made is not afraid of the wind wave higher”, ah