Thoughts on Java concurrent programming and java concurrency
1. Threads and Runnables
All modern operating systems support concurrency through processes and threads. A process is an instance of a program that runs independently of each other. For example, if you start a Java program, the operating system generates a new process and runs it in parallel with other programs. Within these processes, we use threads to execute code concurrently. Therefore, we can maximize the CPU core available ). Java starts to run the thread from JDK1.0. Before starting a new thread, you must specify the code executed by this thread, which is usually called a task. This can be achieved throughRunnable:One that defines a non-return value without Parametersrun()Function interface of the method, as shown in the following code:
Runnable task = ()-> {// Lambda expression in JDK 1.8 String threadName = Thread. currentThread (). getName (); System. out. println ("Hello" + threadName) ;}; task. run (); Thread thread = new Thread (task); thread. start (); System. out. println ("Done! ");
2. Use of java Thread Pool
The above inherits the Thread class and implements the Runnable interface to implement multithreading. However, if the number of concurrent threads is large and every thread executes a short task and ends, frequent thread creation will greatly reduce the system efficiency, it takes time to frequently create and destroy threads. Is there a way to make the thread reusable, that is, to execute a task without being destroyed, but to continue to execute other tasks?In Java, this effect can be achieved through the thread pool.Today, we will explain in detail the Java thread pool. First, let's start with the method in the most core ThreadPoolExecutor class, then introduce its implementation principles, and then provide its example, finally, we discussed how to reasonably configure the thread pool size.
ThreadPoolExecutor class in Java. java... uitl. concurrent. ThreadPoolExecutor class is the core class in the thread pool. Therefore, to thoroughly understand the thread pool in Java, you must first understand this class. Next, let's take a look at the specific implementation source code of the ThreadPoolExecutor class.
public class ThreadPoolExecutor extends AbstractExecutorService { public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler); }
The code above shows that ThreadPoolExecutor inherits the AbstractExecutorService class and provides four constructors. In fact, by observing the specific implementation of the source code of each constructor, it is found that the first three constructors are called by the fourth constructor for initialization. The following describes the meanings of parameters in the constructor:
CoorPoolSize: the size of the core pool. This parameter is closely related to the implementation principle of the thread pool described later. After a thread pool is created, by default, there are no threads in the thread pool. Instead, the thread is created to execute the task only after a task arrives, unless prestartAllCoreThreads () or prestartCoreThread () is called () method. We can see from the names of the two methods that:Pre-creation threadThat is, a corePoolSize thread or thread is created before the task arrives. By default, after a thread pool is created, the number of threads in the thread pool is 0. When a task comes, a thread is created to execute the task, when the number of threads in the thread pool reaches corePoolSize, the tasks that arrive will be placed in the cache queue. maximumPoolSize: the maximum number of threads in the thread pool. This parameter is also a very important parameter, it indicates the maximum number of threads that can be created in the thread pool. keepAliveTime indicates the maximum duration for a thread to terminate when no task is executed. By default, keepAliveTime takes effect only when the number of threads in the thread pool is greater than corePoolSize until the number of threads in the thread pool is not greater than corePoolSize, that is, when the number of threads in the thread pool is greater than corePoolSize, if the idle time of a thread reaches keepAliveTime, it will be terminated until the number of threads in the thread pool does not exceed corePoolSize. However, if the allowCoreThreadTimeOut (boolean) method is called and the number of threads in the thread pool is not greater than the corePoolSize, The keepAliveTime parameter also takes effect until the number of threads in the thread pool is 0; unit parameter: the time unit of keepAliveTime. There are 7 values and 7 static attributes in the TimeUnit class:
TimeUnit. DAYS; // day TimeUnit. HOURS; // hour TimeUnit. MINUTES; // minute TimeUnit. SECONDS; // second TimeUnit. MILLISECONDS; // millisecond TimeUnit. MICROSECONDS; // The subtle TimeUnit. NANOSECONDS; // NANOSECONDS
WorkQueue: a blocking queue used to store tasks waiting for execution. The selection of this parameter is also very important and will have a significant impact on the running process of the thread pool. Generally, the blocking queue here has the following options: