Large Data Processing series (i) Java thread pool usage

Source: Internet
Author: User

Introduction: Recently in the distributed Mass data processing project, the use of Java thread pool, so collected some information on its use to do a summary and explore,

Most of the things that are described above are collected from the Internet. The most important thing in the text is the following two instances of the unbounded queue thread pool and the bounded queue thread pool

Use and online problem-handling scenarios.

1. Why use a thread pool?

In Java, if you create a new thread every time a request arrives, the overhead is quite large. In actual use, each request creates a new thread for the server

The time spent on creating and destroying threads and the amount of system resources consumed may even be much more than the time and resources spent actually processing actual user requests. Except

In addition to the overhead of creating and destroying threads, the active thread also consumes system resources. If too many threads are created in one JVM, it can cause the system to

Excessive consumption of memory or "over-switching" results in insufficient system resources. To prevent resource shortages, server applications need some way to limit any given moment

The number of requests processed, minimizing the number of threads created and destroyed, especially the creation and destruction of some resource-intensive threads, maximizing the use of existing objects

To service, which is why pooled resources technology is being created.

Thread pooling is primarily used to address thread life-cycle overhead and resource-poor issues, and the overhead of thread creation is apportioned across multiple tasks by reusing threads

, and because the thread already exists at the time the request arrives, it eliminates the delay caused by the creation. This allows the service to be requested immediately, making the application sound

should be faster. In addition, you can prevent resource shortages by appropriately resizing thread data in the thread pool.

This phrase, which is found on the Internet, clearly describes why the thread pool is used and the benefits of using the thread pool. The use of thread pools in engineering projects abounds.

The focus of this paper is how to use the technology of thread pool in actual combat to satisfy the scenario of large data concurrent user request.

2. Threadpoolexecutor class

Thread pooling techniques in Java are mainly used in the Threadpoolexecutor class. First look at the constructor of this class,

Threadpoolexecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,

BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

    corePoolSize       线程池维护线程的最少数量

    maximumPoolSize    线程池维护线程的最大数量 

    keepAliveTime      线程池维护线程所允许的空闲时间  

    workQueue          任务队列,用来存放我们所定义的任务处理线程

    threadFactory      线程创建工厂

    handler            线程池对拒绝任务的处理策略

Threadpoolexecutor automatically adjusts the pool size based on the boundaries set by the Corepoolsize and Maximumpoolsize. When new tasks are in the method

When you commit in Execute (Runnable), if you run fewer threads than corepoolsize, a new thread is created to process the request, even if other worker threads are

The idle. If you run more threads than corepoolsize and less than maximumpoolsize, a new thread is created only when the queue is full. If you set the

Corepoolsize and Maximumpoolsize are the same, a fixed-size thread pool is created.

Threadpoolexecutor is the implementation of the executors class, which provides a number of static factories in the executors class, generating some commonly used thread pools, the main

Here are a few:

Newsinglethreadexecutor: Creates a single thread pool. This thread pool has only one thread at work, which is equivalent to single-threaded serial execution

All Tasks. If this unique thread ends because of an exception, a new thread will replace it. This thread pool guarantees that all tasks are executed in the order

Execution of the commit order.

Newfixedthreadpool: Creates a fixed-size thread pool. Each time a task is committed, a thread is created until the thread reaches the maximum size of the threads pool. Line

Once the maximum size of the pool is reached, it remains the same, and if a thread ends up performing an exception, the threads pool complements a new thread.

Newcachedthreadpool: Creates a cacheable thread pool. If the size of the thread pool exceeds the thread that is required to process the task, the part is recycled

A thread that is idle (60 seconds without a task), and when the number of tasks increases, the thread pool can intelligently add new threads to handle the task. This thread pool does not have a thread pool

Size constraints, the thread pool size is entirely dependent on the maximum thread size that the operating system (or JVM) can create.

In the actual project, we will use the more newfixedthreadpool to create a fixed-size thread pool, but this method is on the real line

There are still a lot of problems in the environment, which will be discussed in detail in the next section.

When the task continues to come, and our system does not handle it, the strategy we are going to take is denial of service. Rejectedexecutionhandler Connection

Provides the opportunity to reject custom methods for task handling. There are four processing strategies already included in the Threadpoolexecutor.

1) Callerrunspolicy: The thread invokes the execute itself that runs the task. This strategy provides a simple feedback control mechanism that can slow down the submission of new tasks.

public void Rejectedexecution (Runnable R, Threadpoolexecutor e) {

if (!e.isshutdown ()) {

R.run ();

}

}

This strategy obviously does not want to abandon the task. However, since there are no resources in the pool, it is executed directly using the thread itself that invoked the execute.

2) AbortPolicy: handler rejection will throw runtime rejectedexecutionexception

public void Rejectedexecution (Runnable R, Threadpoolexecutor e) {

throw new Rejectedexecutionexception ();

}

This strategy throws an exception directly, discarding the task.

3) Discardpolicy: Unable to perform the task will be deleted

public void Rejectedexecution (Runnable R, Threadpoolexecutor e) {}

This strategy is almost as much a abortpolicy as a drop-off task, except that he does not throw an exception.

4) Discardoldestpolicy: If the execution program has not been closed, the task in the head of the work queue will be deleted, and then retry the execution of the program (if it fails again,

This process is repeated)

public void Rejectedexecution (Runnable R, Threadpoolexecutor e) {

if (!e.isshutdown ()) {

E.getqueue (). poll ();

E.execute (R);

}

}

The strategy is a little more complicated, with the pool not shutting down and first losing the oldest task cached in the queue, and then trying to run the task again. This strategy

Proper care is required.

3. Threadpoolexecutor Unbounded Queue Usage

public class ThreadPool {

Private final static String poolname = "Mypool";

static private ThreadPool Threadfixedpool = new ThreadPool (2);

Private Executorservice executor;

static public ThreadPool getfixedinstance () {

return threadfixedpool;

}

Private ThreadPool (int num) {

Executor = Executors.newfixedthreadpool (num, new Daemonthreadfactory (poolname));

}

public void Execute (Runnable r) {

Executor.execute (R);

}

public static void Main (string[] params) {

Class Myrunnable implements Runnable {

public void Run () {

System.out.println ("ok!");

try {

Thread.Sleep (10);

} catch (Interruptedexception e) {

E.printstacktrace ();

}

}

}

for (int i = 0; i < i++) {

Threadpool.getfixedinstance (). Execute (New myrunnable ());

}

try {

Thread.Sleep (2000);

System.out.println ("Process end.");

} catch (Interruptedexception e) {

E.printstacktrace ();

}

}

}

In this code, we find that we have used the Executors.newfixedthreadpool () function, which is the implementation of this function:

return new Threadpoolexecutor (Nthreads, Nthreads, 0L, Timeunit.milliseconds,new linkedblockingqueue<runnable> ( ));

It is actually a fixed-size thread pool that creates a unbounded queue. Executing this code, we find that all the tasks are handled properly. But on the real line loop,

There is a problem in the environment, the front end of the user request flow, the back end of the processing thread if the processing time is longer, unable to quickly process the user request

When the result is returned to the front end, a large number of requests are blocked in the task queue. These requests have a timeout setting on the front-end, assuming the request is coming through the socket,

When our backend processing process finishes processing a request and takes the next task from the queue, it is found that the socket for this task is invalid because the client has already

Timeout, the connection established by the socket is closed. i/0 Exception occurs when the handler on our side reads the socket again. Vicious circle that led me

All the processing service threads read the timeout socket, all requests come over to throw I/O exception, so that our entire system is hung up, has been unable to provide external

Normal service.

For the processing of large amounts of data, the industry is now using a cluster system for processing, when the number of requests is increasing, we can increase the processing node, anyway

The hardware device is relatively inexpensive. However, in order to ensure the reliability and stability of the system, we can further optimize the program, our next sectionto is about

A processing strategy for this type of problem that occurs on the line.

4. Threadpoolexecutor Bounded queue usage

public class ThreadPool {

Private final static String poolname = "Mypool";

static private ThreadPool Threadfixedpool = null;

Public arrayblockingqueue<runnable> queue = new arrayblockingqueue<runnable> (2);

Private Executorservice executor;

static public ThreadPool getfixedinstance () {

return threadfixedpool;

}

Private ThreadPool (int num) {

Executor = new Threadpoolexecutor (2, 4,60,timeunit.seconds, Queue,new daemonthreadfactory

(poolname), New Threadpoolexecutor.abortpolicy ());

}

public void Execute (Runnable r) {

Executor.execute (R);

}

public static void Main (string[] params) {

Class Myrunnable implements Runnable {

public void Run () {

System.out.println ("ok!");

try {

Thread.Sleep (10);

} catch (Interruptedexception e) {

E.printstacktrace ();

}

}

}

int count = 0;

for (int i = 0; i < i++) {

try {

Threadpool.getfixedinstance (). Execute (New myrunnable ());

} catch (Rejectedexecutionexception e) {

E.printstacktrace ();

count++;

}

}

try {

Log.info ("Queue size:" + threadpool.getfixedinstance (). Queue.size ());

Thread.Sleep (2000);

} catch (Interruptedexception e) {

E.printstacktrace ();

}

SYSTEM.OUT.PRINTLN ("Reject task:" + count);

}

}

First, let's look at some important parameters of this code,corePoolSize 为2,maximumPoolSize为4,任务队列大小为2,每个任务平

均处理时间为10ms,一共有10个并发任务。

Executing this code, we will find that 4 tasks have failed. This validates the order in which the thread pool executes when we refer to a bounded queue. When a new task is

When you commit in method Execute (Runnable), if you run fewer threads than corepoolsize, a new thread is created to process the request. If you are running more threads than

Corepoolsize and less than maximumpoolsize, a new thread is created only when the queue is full, and if the number of threads reaches maximumpoolsize at this point, and the team

When the column is full, the request will be refused to go in.

Now let's tweak some of the parameters in the code, change the number of concurrent tasks to 200, and execute the results reject task:182, stating that 18 tasks were successful, threading

After a request is completed, the next request is processed. In the real online environment, there will be a steady stream of new requests coming in, the current is rejected, but as long as the line

The pool thread can handle the next request that is sent after the current task has been processed.

Through the bounded queue can realize the overload protection of the system, in the case of high pressure, our system processing capacity will not become 0, but also normal external service, though some services

May be rejected, as to how to reduce the number of rejections and how to deal with rejected requests I will continue in the next article, "System Overload protection"

elaborated

Large Data Processing series (i) Java thread pool usage

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.