A little summary of the thread

Does the main method in java start a process or a thread?
Answer: A thread is also a process. After a java program is started, it is a process. The process is equivalent to an empty box. It only provides space for resource loading. The specific scheduling is not completed by the process, but by the thread. Completed. After a java program starts from main, the process starts to provide various resources for the whole program, and at this time, a thread is started, which is the main thread, which will schedule resources and perform specific operations. The threads opened by Thread and Runnable are child threads under the main thread, which is a parent-child relationship. At this time, the java program is multi-threaded, and these threads work together to schedule and execute resources.

When each Java service is started, it is equivalent to starting a process. For example, in
a daily interface project, every time we request an interface in the controller, a new thread will be started when each request comes into the service, and the system will start a new thread. A thread, until the request is executed and returned to the caller, the system automatically releases the thread, this is the main thread, during the execution of the main thread, if we start a new thread by ourselves or we call some other controls or methods Start new threads here, these are newly started threads, these threads have nothing to do with the main thread, they are all different threads.


Java provides four thread pools through Executors:
newCachedThreadPool creates a cacheable thread pool. If the length of the thread pool exceeds the processing requirement, idle threads can be flexibly recovered. If there is no recovery, a new thread will be created.
newFixedThreadPool creates a fixed-length thread pool that can control the maximum number of concurrent threads. Exceeded threads will wait in the queue.
newScheduledThreadPool creates a fixed-length thread pool that supports scheduled and periodic task execution.
newSingleThreadExecutor creates a single-threaded thread pool that only uses a single worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).


(1) newCachedThreadPool
creates a cacheable thread pool. If the length of the thread pool exceeds the processing needs, it can flexibly recycle idle threads. If there is no recovery, create a new thread. The thread pool is infinite. When the second task is executed, the first task has been completed, and the thread executing the first task will be reused instead of creating a new thread each time. The sample code is as follows:
public class ThreadPoolExecutorTest {
    // start a main main thread when the main method is executed
    public static void main(String[] args) {
        // Thread Pool
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                // The current ready-made sleep index*1000 milliseconds, the current thread is the main thread of the main method
                Thread.sleep(index * 1000);
                // print the name of the thread where the current code is executing
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
            // Call the thread pool to start a thread, which is a child thread of the main thread
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    // The thread taken from the thread pool is released directly after execution, so the next time the loop takes a thread from the thread pool to execute this print may still use the same thread
                    System.out.println(index);
                    // Print the name of the thread where the current code is executed (should be the name of the thread taken from the thread pool)
                    System.out.println("========================" + Thread.currentThread().getName());
                }
            });
        }
    }
}


public class ThreadPoolExecutorTest {
    // start a main main thread when the main method is executed
    public static void main(String[] args) {
        // Thread Pool
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                // The current ready-made sleep index*1000 milliseconds, the current thread is the main thread of the main method
                Thread.sleep(index * 1000);
                // print the name of the thread where the current code is executing
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
            // Call the thread pool to start a thread, which is a child thread of the main thread
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    System.out.println(index);
                    // Print the name of the thread where the current code is executed (should be the name of the thread taken from the thread pool)
                    System.out.println("========================" + Thread.currentThread().getName());
                    try {
                        // The current thread is sleeping, so it is possible that the current thread will not be released after the printing above the loop is executed, and the thread will be taken from the thread pool when the loop comes in next time.
                        // If it is found that the thread that was executed last time is still sleeping and occupied, the thread pool will allocate a new thread to it to execute the printing of the current loop. probably last executed
                        // The thread used can be released after a while. After it is released, it can be taken out of the thread pool and can continue to be used.
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace ();
                    }
                }
            });
        }
    }
}


(2) newFixedThreadPool
creates a fixed-length thread pool, which can control the maximum number of concurrent threads, and the excess threads will wait in the queue. The sample code is as follows:
public class ThreadPoolExecutorTest {
    // start a main main thread when the main method is executed
    public static void main(String[] args) {
        // There are at most 3 threads in the thread pool. If all three threads are occupied, and there is a new request to take a thread from the thread pool, then you can only queue up and wait for the three occupied threads to be released
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            System.out.println("The current main thread is: " + Thread.currentThread().getName());
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        System.out.println("==========================" + Thread.currentThread().getName());
                        // Because the thread pool size is 3, each task sleeps for 2 seconds after outputting the index, so 3 numbers are printed every two seconds. The three threads created in the thread pool are reused again and again
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace ();
                    }
                }
            });
        }
    }
}


Because the thread pool size is 3, each task sleeps for 2 seconds after outputting the index, so 3 numbers are printed every two seconds.
The size of the fixed-length thread pool is best set according to system resources. Such as Runtime.getRuntime().availableProcessors()

(3) newScheduledThreadPool
creates a fixed-length thread pool to support timing and periodic task execution. The sample code for delayed execution is as follows:
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
  scheduledThreadPool.schedule(new Runnable() {
   public void run() {
    System.out.println("delay 3 seconds");
   }
  }, 3, TimeUnit.SECONDS);
 }
}


Indicates a delay of 3 seconds to execute.
Regularly execute the sample code as follows:
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
  scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
   public void run() {
    System.out.println("delay 1 seconds, and excute every 3 seconds");
   }
  }, 1, 3, TimeUnit.SECONDS);
 }
}


Indicates that it will be executed every 3 seconds after a delay of 1 second.

(4) newSingleThreadExecutor
creates a single-threaded thread pool, which only uses a single worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority). The sample code is as follows:
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
  for (int i = 0; i < 10; i++) {
   final int index = i;
   singleThreadExecutor.execute(new Runnable() {
    public void run() {
     try {
      System.out.println(index);
      Thread.sleep(2000);
     } catch (InterruptedException e) {
      e.printStackTrace ();
     }
    }
   });
  }
 }
}


The results are output in sequence, which is equivalent to executing each task in sequence.
You can use the monitoring tool that comes with JDK to monitor the number of threads we create, run a non-terminating thread, and create a specified number of threads to observe:
Tools directory: C:\Program Files\Java\jdk1.6.0_06\bin The \jconsole.exe
running program is slightly modified:

package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ExecutorService singleThreadExecutor = Executors.newCachedThreadPool();
  for (int i = 0; i < 100; i++) {
   final int index = i;
   singleThreadExecutor.execute(new Runnable() {
    public void run() {
     try {
      while(true) {
       System.out.println(index);
       Thread.sleep(10 * 1000);
      }
     } catch (InterruptedException e) {
      e.printStackTrace ();
     }
    }
   });
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace ();
   }
  }
 }
}


Let's do some more in-depth underlying explanations (just look at it briefly):
http://blog.csdn.net/w2393040183/article/details/52177572

Thread pool underlying class library inheritance relationship:






When using the spring framework, if we use The method provided by java to create a thread pool is very inconvenient to manage in multi-threaded applications, and it does not conform to our idea of ​​using spring. (Although spring can be injected through static methods)
In fact, Spring itself also provides a very good thread pool implementation. This class is called ThreadPoolTaskExecutor.
The configuration in spring is as follows:
<bean id="executorService" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="${threadpool.corePoolSize}" />
    <!-- The minimum number of thread pool maintenance threads-->
    <property name="keepAliveSeconds" value="${threadpool.keepAliveSeconds}" />
    <!-- The idle time allowed by the thread pool maintenance thread-->
    <property name="maxPoolSize" value="${threadpool.maxPoolSize}" />
    <!-- The maximum number of thread pool maintenance threads-->
    <property name="queueCapacity" value="${threadpool.queueCapacity}" />
    <!-- The buffer queue used by the thread pool -->
  </bean>


Of course, you can also declare ThreadPoolTaskExecutor in the Java class to define the thread pool, for example:
public final class ThreadPoolUtil {

    // The thread pool maintains the minimum number of threads
    private static final int COREPOOLSIZE = 5;
    // The maximum number of thread pool maintenance threads
    private static final int MAXINUMPOOLSIZE = 20;
    // The thread pool maintains the idle time allowed by the thread
    private static final long KEEPALIVETIME = 5;
    // Thread pool maintains the unit of idle time allowed for threads
    private static final TimeUnit UNIT = TimeUnit.MINUTES;
    // The buffer queue used by the thread pool
    private static final BlockingQueue<Runnable> WORKQUEUE = new ArrayBlockingQueue<>(100);
    // The thread pool's processing strategy for rejected tasks:
    /*
     * AbortPolicy throws an exception
     * CallerRunsPolicy adds the current task for retry, and automatically calls the execute() method repeatedly
     * DiscardOldestPolicy for discarding old tasks
     * DiscardPolicy to discard the current task
     */
    private static final CallerRunsPolicy HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(COREPOOLSIZE, MAXINUMPOOLSIZE, KEEPALIVETIME, UNIT, WORKQUEUE, HANDLER);

    public static void execute(Runnable r) {
        executor.execute(r);
    }

    public static boolean isShutDown() {
        return executor.isShutdown();
    }

    public static void shutDownNow() {
        executor.shutdownNow();
    }

    public static void shutdown() {
        executor.shutdown();
    }
}


Notes on using thread pools
• Deadlock
Any multi-threaded program has the risk of deadlock. The simplest case is two threads AB, A holds lock 1 and requests lock 2, and B holds lock 2 and requests lock 1. (This situation will also occur in the exclusive lock of mysql, and the database will not report an error directly). There is another kind of deadlock in the thread pool: Suppose all the worker threads in the thread pool are blocked while executing their respective tasks, they are waiting for the execution result of some task A. However, task A is in the queue and cannot be executed because there are no idle threads. In this way, all the resources of the thread pool will be blocked all the time, and a deadlock will occur.
• Insufficient system resources
If the number of threads in the thread pool is very large, these threads will consume a lot of resources including memory and other system resources, which will seriously affect the system performance.
• Concurrency error The
thread pool's work queue relies on wait() and notify() methods to make worker threads obtain tasks in a timely manner, but these two methods are difficult to use. If the code is wrong, notifications may be lost, causing worker threads to remain idle, ignoring tasks that need to be processed in the work queue. Because it is better to use some more mature thread pools.
• Thread leaks A serious risk of
using thread pools is thread leaks. For a thread pool with a fixed number of worker threads, if a worker thread throws a RuntimeException or Error while executing a task, and these exceptions or errors are not caught, then the worker thread terminates abnormally, causing the thread pool to permanently lose a thread. (This is too interesting)
Another situation is that the worker thread is blocked when executing a task. If it waits for the user's input data, but the user has not input data, the thread is blocked all the time. Such a worker thread exists in name only, it doesn't actually perform any tasks anymore. If all threads in the thread pool are in this state, then the thread pool cannot add new tasks.
• Task overload
When there are a large number of tasks queued for execution in the worker thread queue, these tasks themselves may consume too many system resources and cause resource starvation.
To sum up, when using the thread pool, the following principles should be followed:
1. If task A needs to wait for the execution result of task B synchronously during the execution process, then task A is not suitable to be added to the work queue of the thread pool. If you add tasks like task A that need to wait for the execution results of other tasks to be added to the queue, it may cause deadlock
2. If a task may be blocked when executing, and it is blocked for a long time, you should set a timeout to avoid Worker threads are permanently blocked causing thread leaks. In the server program, when the thread waits for the client to connect or wait for the data sent by the client, it may cause blocking. You can set the time by the following methods:
call the setSotimeout method of ServerSocket to set the timeout time for waiting for the client to connect.
For each socket connected to the client, call the setSoTImeout method of the socket to set the timeout period for waiting for the client to send data.
3. Understand the characteristics of the task, and analyze whether the task performs an io operation that often blocks or performs an operation that does not block all the time. The former occupies the CPU intermittently, while the latter has higher utilization. Estimate how long it will take to complete the task, whether it is a short-term task or a long-term task, and then classify the tasks according to the characteristics of the tasks, and then add different types of tasks to the work queues of different thread pools, so that according to The characteristics of the task, the allocation adjustment of each thread pool
4. Adjust the size of the thread pool. The optimal size of the thread pool mainly depends on the number of available CPUs in the system and the characteristics of the tasks in the work queue. If there is only one work queue on a system with N CPUs, and all of them are computational (non-blocking) tasks, then when the thread pool has N or N+1 worker threads, the maximum CPU usage will generally be obtained. Rate.
If the work queue contains tasks that perform IO operations and block frequently, make the thread pool size larger than the number of available CPUs, because not all worker threads are working all the time. Choose a typical task, and then estimate the ratio WT/ST of the waiting time to the time actually occupied by the CPU to perform operations in the project that executes this task. For a system with N CPUs, it is necessary to set about N*(1+WT/ST) threads to ensure that the CPUs are fully utilized.
Of course, CPU utilization is not the only thing to consider when tuning the thread pool. As the number of thread pool jobs grows, you will also encounter memory or other resource constraints, such as sockets, open file handles or the number of database connections. Wait. It is necessary to ensure that the system resources consumed by multi-threading are within the range that the system can bear.
5. Avoid task overload. The server should limit the number of concurrent client connections based on the system's carrying capacity. When the client's connection exceeds the limit value, the server can refuse the connection and give a friendly prompt, or limit the queue length.
The above several implementation methods and frequently asked questions of the Java thread pool are all the content shared by the editor. I hope it can give you a reference, and I hope you will support Script Builder more.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326979659&siteId=291194637