Java thread pool share __ thread pool

Source: Internet
Author: User
Tags inheritance mutex semaphore thread class zookeeper

Summary thread pool Working principle construction method Survival time KeepAliveTime surviving time Unit uunit task Queue Workqueue thread factory Threadfactory deny policy handler the basic process of a task execution submit a task to the thread pool execute SU Bmit closes the thread pool executors frame Newcachedthreadpool caused by the Oom Newsinglethreadexecutor the deadlock blocking signal traffic fence

Summary

Speaking of the process of everyone is not unfamiliar, learned the operating system must know. And in order not to cause the process to be blocked because of some improper operation, the process appears. A thread can be created in a process that is a smaller granularity than the process. We all know to create a thread by inheriting the thread class, or by implementing the Runnable interface, while creating and destroying threads in a process consumes a lot of time, and a large number of child threads share the main thread's system resources. This will cause the main thread to be limited by the resources to reduce the application to reduce the time that the thread consumes in the process of creating and destroying, in order to solve these problems, the thread pool is born. How the thread pool works

First look at an example:

Assume that the time to complete a task on a single server is T
T1 the time the thread was created
T2 time to perform a task in a thread, including the time required for synchronization between threads
T3 the time the thread was destroyed
Then T = t1+t2+t3.

Analyze:
T1,t3 is the overhead of multithreading itself, hoping to reduce the time spent by T1,T3, thereby reducing t time. If threads are created or destroyed frequently in a program, this causes T1 and T3 to occupy a significant proportion of the T. Obviously this is highlighting the thread's weaknesses (T1,T3), not the benefits (concurrency). Thread pooling technology is a technology that focuses on how to shorten or adjust t1,t3 time, thereby improving server program performance

and thread creation is not just as simple as our new thread. When the JVM gives the task of creating threads to the OS, the cost of creating a thread on the OS is very expensive, it needs to allocate memory to this thread, include the schedule, when the threads switch to the memory page, empty the CPU cache, switching back from memory to read information, damage the local nature of the data.
And then take a look at our thread pool.
In the Java.util.concurrent package, there is a class threadpoolexecutor, viewing his inheritance relationship we can find
Executor: The interface thread pool must be implemented in an interface where only one method is the Execute method. Submit Task Executorservice: Interface Inheritance Executor interface increases the way in which submit tasks are submitted (with return values) and close operations Abstractexecutorservice all methods that implement Executorservice
Threadpoolexecutor is the thread pool class we use.

And we usually create a new thread pool that uses the executors static method for creating several common threads pools. These common thread pools are basically implemented by creating a new Threadpoolexecutor method.
So before we introduce the use of the executors thread pool, we first introduce a Threadpoolexecutor construction method

 public threadpoolexecutor (int corepoolsize, int maximumpoolsize
                              , Long KeepAliveTime, Timeunit unit,
                              Blockingqueue<runnable> Workqueue, Threadfactory threadfactory, Rejectedexecutionhandler handler) 
variable meaning
Corepoolsize Core thread pool Size
Maximumpoolsize Maximum thread pool size
KeepAliveTime Time to live idle threads
Unit The unit of time that the idle thread remains alive
Workqueue Blocks the task queue, and when the task to be performed exceeds corepoolsize, the task is placed in the queue.
Threadfactory Create a factory used by threads
Handler Reject policy when committing a task beyond Maxmumpoolsize+workqueue
survival Time (KeepAliveTime)

The KeepAliveTime is the idle thread (a thread greater than corepoolsize less than maximumpoolsize) to remain alive for the time that the thread will be destroyed. If Allowcorethreadtimeout (true) is set, the core thread will be destroyed in excess of idle time units U (unit)

Idle thread surviving unit of time, optionally having

Timeunit.nanoseconds        //      1 per thousand microseconds (nanosecond)
timeunit.microseconds       //      1 per thousand ms (subtle)
Timeunit.milliseconds       //      1 per thousand sec (ms)
Timeunit.seconds/      sec       
timeunit.minutes            //      points
Timeunit.hours              //      hour
timeunit.days               //      Day
task Queues (workqueue)Arrayblockingqueue: is a bounded blocking queue based on an array structure that sorts the elements in FIFO (first-in first out) principle. Linkedblockingqueue: A blocking queue based on a linked list structure that is sorted by FIFO (first-in first out) and typically has a higher throughput than arrayblockingqueue. The static Factory Method Executors.newfixedthreadpool () uses this queue. Synchronousqueue: A blocking queue that does not store elements. Each insert operation must wait until another thread calls the removal operation, or the insert operation is always blocked, the throughput is usually higher than linkedblockingqueue, and the static factory method Executors.newcachedthreadpool uses the queue. Priorityblockingqueue: An infinite blocking queue with precedence. - Thread Factory (threadfactory)

Each time a thread needs to create a thread, it is through the threading factory method. The default thread factory method creates a new, non-guarded thread and does not contain special configuration information. By customizing a thread factory, you can customize the thread pool configuration information. For example, you can customize a thread factory when you want to maintain some statistics for threads in the thread pool (how many threads are created and destroyed) and debug message writes to log when a thread is created or terminated. reject Policy (handler)

When a bounded queue is filled, the rejection policy starts to work, the JDK provides a centralized rejectedexecutionhandler implementation, and each implementation has a different saturation strategy. AbortPolicy Abort policy: The default Saturation policy, which will be thrown as a check rejectedexecutionexception. The caller can catch this exception and then write their own code as needed. Discardpolicy Discard policy: When a newly submitted task cannot be saved to the queue for execution, the discard policy silently discards the task Discardoldestpolicy discard the oldest policy: Discard the next task that will be performed, and then add the newly submitted task Callerrunspolicy The caller runs the policy: This policy implements an invocation mechanism that neither discards the task nor throws an exception, but returns some tasks back to the caller, thereby reducing the flow of the new task. It does not perform the newly committed task in one thread of the pool, but rather the basic process of executing the task in a thread that calls execute (typically the caller is the main thread)


Looking at the source, we can see the thread pool task execution process: When the number of threads in the thread pool is less than corepoolsize, the newly committed task creates a new thread directly to perform the task (regardless of whether there is an idle thread), and when the number of threads in the thread pool equals corepoolsize, The newly submitted task will go into the blocking queue (workqueue), waiting for the thread to schedule when the blocking queue is full, and if Corepoolsize < Maximumpoolsize, the newly committed task will create a new thread to perform the task. Until the number of threads reaches Maximumpoolsize

When the number of threads reaches Maximumpoolsize, the newly committed task is managed by the (saturation policy)

Here is a simple test of callerrunspolicy strategy
We created a new thread pool with a core thread size and a maximum thread size of 1, then set its reject policy to callerrunspolicy, and then output the name of the threads that the task executes.

/**
 * *
 @author xiaosuda
 * @date 2018/1/8/public
class Callerrunspolicytest {public

    static void Main (String [] args) {
        Threadpoolexecutor threadpoolexecutor = new Threadpoolexecutor (1, 1, timeunit.seconds , New linkedblockingdeque<> (1), New Threadpoolexecutor.callerrunspolicy ());
        for (int i = 0; i < 3 i++) {
            Threadpoolexecutor.execute ()-> {
                try {
                    System.out.println (thread.curren TThread (). GetName ());
                    Thread.Sleep (1000);
                } catch (Interruptedexception e) {
                    e.printstacktrace ();}}
            );
        Threadpoolexecutor.shutdown ();
    }

Output results:

Pool-1-thread-1
Main
Pool-1-thread-1

Analysis: Because the core thread pool + blocked Queue size = 2, and we created 3 new tasks. When the first task is submitted, the new thread performs the task, and when the second task is submitted, the thread pool has a core size of 1 and the task is executing, putting the blocking queue, and when submitting the third task, the blocked queue is full and the maximum number of threads in the thread pool is maximized. So it is handled by the rejection policy, and the Callerrunspolicy reject policy returns the task back to the caller (main thread), which reduces the flow of the new task. submitting tasks to the thread pool Execute

We can submit a task to the thread pool using the void execute (Runnable command) method, but the method has no return value

Executorservice Cachedthreadpool = Executors.newcachedthreadpool ();
 Cachedthreadpool.execute (New Runnable () {
             @Override public
             void Run () {
                 //do some things
             }
         });
Submit

We can also use the Future submit (callable Task) method to submit a task. It returns a future object, and we can get the return value through Future.get, which blocks until the thread executes successfully or throws an exception. We can also use get (long timeout, timeunit) to block for a period of time and return immediately, when the task may not have been successfully executed. Use the scene: for example, when we use the high-German map to find a route to a particular place (there may be many routes, but it takes a different amount of time to compute the route), we can set a time-out to show only those routes that have been calculated.
For example, we're going to get a random number within 100.

Executorservice Executorservice = Executors.newsinglethreadexecutor ();

        future<integer> randomnum = executorservice.submit (new callable<integer> () {
            @Override
            public Integer call () throws Exception {return
                new Random (). Nextint ();
            }
        });
        try {
            System.out.println (Randomnum.get ());
        } catch (Interruptedexception e) {
            //Break Exception
            E.printstacktrace ();
        } catch (Executionexception e) {
            ///Task Exception
            e.printstacktrace ();
        } finally {
            //close thread pool
            Executorservice.shutdown ();
        }
Close the thread pool

The

provides two methods of closing a thread pool in threadpoolexecutor. Shutdown Shutdownnow
View the source, we can find that
shutdown: The state of the thread pool is modified to shutdown, the task cannot be added to the thread pool, or the added task is handled by the deny policy. However, the tasks that have been added (the tasks in the task queue and the tasks being performed) continue to execute until they are complete, and then the thread pool exits.
Shutdownnow: Modify the state of the thread pool to stop, the task cannot be added to the thread pool, or the added task is handled by a deny policy. and the tasks in the task queue are no longer executing, only performing the tasks that are being performed, and attempting to break them, and then return those tasks that were not performed, and the thread pool exits.

/** * * @author Xiaosuda * @date 2018/1/8/public class Shutdownnowtest {public static void main (String [] Arg
        s) {Integer threadnum = Runtime.getruntime (). Availableprocessors ();
        Threadfactorybuilder Threadfactorybuilder = new Threadfactorybuilder ();
        Threadfactorybuilder.setnameformat ("Shutdownnowtestpool");
        Threadfactory threadfactory = Threadfactorybuilder.build (); Threadpoolexecutor threadpoolexecutor = new Threadpoolexecutor (1, Threadnum, 60L, Timeunit.seconds, new

        Linkedblockingdeque<> (5), Threadfactory, New Threadpoolexecutor.abortpolicy ());
            for (int i = 0; i < i++) {String content = "Thread-name" + i;
                    Threadpoolexecutor.execute (New Runnable () {@Override public void run () {
                    Thread.CurrentThread (). SetName (content);
                    int x = 10000; To simulate long time tasks, avoid tasks in the queue without tasks while (x--> 0) {

                    } System.out.println (Thread.CurrentThread (). GetName ());
        }
            });
        } list<runnable> Runnables = Threadpoolexecutor.shutdownnow ();
        System.out.println ("--------------------------------of tasks not performed--------------------------------");
        for (Runnable runnable:runnables) {new Thread (Runnable). Start ();
 }
    }
}
Execution results:

Thread-name0
Thread-name6
Thread-name1
Thread-name2
Thread-name3
Thread-name7
—————————— – Tasks that are not performed —————————— –
Thread-name8
Thread-name4
Thread-name5
Thread-name9 executors Framework in EXECUTORS,JDK provides us with several common thread pools Newfixedthreadpool: At this point the number of core thread pools equals the maximum number of thread pooling. A fixed-length thread pool is created, and the blocking queue uses linkedblockingqueue, which the thread can reuse. Newcachedthreadpool: Create a thread pool that can be cached, the default core thread pool number is 0, the maximum number of thread pools is integer.max_value. The blocking queue uses the Synchronousqueue. The thread survives at 60s. Once a task is submitted, create a new thread to perform the task, if there are idle threads exceeding 60s automatic recycling, when the demand increases massively, and the task execution time is longer, it is easy to oom, at this time can use the semaphore to control the number of simultaneous execution threads. Newsinglethreadexecutor: Creates a thread pool with core threads and a maximum number of threads of 1, blocking queues for linkedblockingqueue. Serial execution of the task, if you want to avoid deadlocks if you add a task to the thread pool in the thread. Newscheduledthreadpool: Creates a fixed-length thread pool and performs tasks in a deferred or timed manner. Newcachedthreadpool caused by the Oom

A new Cachedthreadpool was created, and the task was added to sleep 100 milliseconds to reach the target of a long task. Adds a task to the Cachedthreadpool loop.

/**
 * *
 @author xiaosuda
 * @date 2018/1/3/public
class Testexecutorsthread {public

    static void Main (String [] args) {
        cachethreadpool ();
    }
    private static void Cachethreadpool () {
        Executorservice Cachedthreadpool = Executors.newcachedthreadpool ();
        for (int i = 0; i < Integer.max_value i++) {
            cachedthreadpool.execute ()->{
                    try {
                        Thread.Sleep (100 );
                    } catch (Interruptedexception e) {
                        e.printstacktrace ();}}
            );
        Cachedthreadpool.shutdown ();
    }

After the execution of the results found Oom:

Exception in thread ' main ' java.lang.OutOfMemoryError:unable to ' create new native thread at
    java.lang.Thread.start0 ( Native method) at
    Java.lang.Thread.start (thread.java:717)
    at Java.util.concurrent.ThreadPoolExecutor.addWorker (threadpoolexecutor.java:950) at
    Java.util.concurrent.ThreadPoolExecutor.execute (threadpoolexecutor.java:1368) at
    Com.dfire.Thread.TestExecutorsThread.cacheThreadPool (testexecutorsthread.java:19) at
    Com.dfire.Thread.TestExecutorsThread.main (TESTEXECUTORSTHREAD.JAVA:14)

So we should be careful when using newcachedthreadpool to avoid adding long time tasks, or limit the number of concurrent tasks. Newsinglethreadexecutor caused by the deadlock

Because Newsinglethreadexecutor creates a single thread, the tasks are executed serially, and if dependencies between tasks arise, deadlocks can occur easily. Here's an example of a newsinglethreadexecutor deadlock.

/** * * @author Xiaosuda * @date 2018/1/8/public class Singlethreadexecutortest {public static void main (Stri ng [] args) throws Executionexception, interruptedexception {executorservice singlethreadexecutor = executors.new
        Singlethreadexecutor ();
        Random Random = new Random ();
            future<integer> randomsum = singlethreadexecutor.submit (new callable<integer> () {@Override Public Integer Call () throws Exception {future<integer> Randomone = SINGLETHREADEXECUTOR.SUBM It (new callable<integer> () {@Override public Integer call () throws Exceptio
                    n {return random.nextint (100);
                }
                }); future<integer> randomtwo = singlethreadexecutor.submit (new callable<integer> () {@Overrid
                     E public Integer Call () throws Exception {   Return Random.nextint (100);
                }
                });
            return Randomone.get () + randomtwo.get ();
        }
        });
    System.out.println (Randomsum.get ());
 }
}

The program has been executing, but there is no result output, the jstack-l [PID]->thread.jstack command Analysis
opens the Thread.jstack and finds that:

2018-01-08 12:38:52 full thread dump Java HotSpot (TM) Client VM (25.131-b11 mixed mode): "Pool-1-thread-1" #11 prio=5 Os_ Prio=0 tid=0x14e47c00 nid=0x1278 waiting on condition [0x155ff000] Java.lang.Thread.State:WAITING (parking) at Sun . misc. Unsafe.park (Native method)-Parking to wait for <0x04750dd0> (a java.util.concurrent.FutureTask) at java.u Til.concurrent.locks.LockSupport.park (locksupport.java:175) at Java.util.concurrent.FutureTask.awaitDone ( futuretask.java:429) at Java.util.concurrent.FutureTask.get (futuretask.java:191) at Com.dfire.Thread.SingleThreadE Xecutortest$1.call (singlethreadexecutortest.java:31) at Com.dfire.thread.singlethreadexecutortest$1.call ( SINGLETHREADEXECUTORTEST.JAVA:16) at Java.util.concurrent.FutureTask.run (futuretask.java:266) at Java.util.concurr Ent. Threadpoolexecutor.runworker (threadpoolexecutor.java:1142) at Java.util.concurrent.threadpoolexecutor$worker.run (threadpoolexecutor.java:617) at Java.lang. Thread.run (thread.java:748) Locked ownable synchronizers:-<0x04742ca0> (a Java.util.concurrent.ThreadPoolE
 Xecutor$worker)

A deadlock occurred in the thread. Latching

A synchronization tool class that can delay the progress of a thread until it reaches the end state, which is the equivalent of a door, which is closed until the lock reaches the end state, and no thread can pass. When the lockout reaches the end state, it will not change the state, so the keeper stays open forever, and the latch can be used to ensure that certain activities are completed before continuing.
Countdownlatch is a kind of flexible latching implementation.
For example: a simple zookeeper connection.

/** * @author Xiaosuda * @date 2018/01/08/public class Connectionwatcher implements watcher {private static F
    inal int session_timeout = 5000;
    Protected zookeeper zookeeper;


    Private Countdownlatch connectedsignal = new Countdownlatch (1); public void Connect (String hosts) throws IOException, interruptedexception {zookeeper = new Zookeeper (hosts, Sess
        Ion_timeout, this);
    Connectedsignal.await (); @Override public void process (Watchedevent watchedevent) {if watchedevent.getstate () = = Event.keepers Tate.
            syncconnected) {Connectedsignal.countdown ();
        System.out.println ("connected successfully");
        } public void Close () throws Interruptedexception {zookeeper.close ();
    SYSTEM.OUT.PRINTLN ("Connection close"); public static void Main (String [] args) throws IOException, Interruptedexception, keeperexception {Connect
        Ionwatcher connectionwatcher = new Connectionwatcher (); ConnectiOnwatcher.connect ("117.88.151.70:2181");
    Connectionwatcher.close ();
 }
}

Here we use the Countdownlatch, and the counter's initial value is 1. In the Connect method, we use Connectedsignal.await () to enter the wait state. The Connectionwatcher class implements the Watcher interface, and does not override the process method. In the process method, if the connection succeeds, the value of the counter is 1, and the wait state becomes the end. The subsequent operation that started the successful connection execution.
There are also futuretask that can be used as a latching (Futuretask implements future semantics, representing an abstract, computable result). The behavior of the future.get depends on the state of the task, and if the task is completed, then the get returns the result immediately, or the block knows that the task is in the completed state, then returns the result or throws an exception. Signal Volume

Semaphores (semaphore) are used to control the number of operations that access a particular resource at the same time, or to perform a certain number of operations at the same time, and semaphores can be used to implement a resource pool, or to impose boundaries on a container.
There are two commonly used methods of semaphores:
Semaphore manages a set of virtual licenses, and the initial state of the license can be performed through constructors, which can be licensed first and then released after use. If there is no license, then Semaphore.acquire () will block until there is a license. The Semaphore.release () method returns a license semaphore. A simplified form of a semaphore is a two-value semaphore, or semaphore with an initial value of 1. Binary semaphore can be a mutex, does not have the lock semantics, who has the only license, has a mutex. In the oom caused by the above Newcachedthreadpool, we can use the semaphore to control the concurrency of the task. The modified code is as follows:

/**
 * *
 @author xiaosuda
 * @date 2018/1/3/public
class Testexecutorsthread {
    private static Integer max_task = m;
    private static semaphore semaphore = new semaphore (max_task);
    public static void Main (String [] args) throws Interruptedexception {
        cachethreadpool ();
    }
    private static void Cachethreadpool () throws interruptedexception {
        Executorservice cachedthreadpool = Executors.newcachedthreadpool ();
        for (int i = 0; i < Integer.max_value i++) {
            semaphore.acquire ();
            Cachedthreadpool.execute (()->{
                try {
                    thread.sleep ();
                } catch (Interruptedexception e) {
                    E.printstacktrace ();
                } finally {
                    semaphore.release ();}}
            );
        Cachedthreadpool.shutdown ();
    }

After execution, it is found that oom will not appear and that it will eventually succeed. Fences

We have seen a set of related actions to be initiated by blocking, or waiting for a set of related operations to end. Locking is a one-time object, once entered the termination state, can not be reset. The fence is similar to latching, which blocks a group of threads from knowing that an event has occurred. The difference between a fence and a lock is that all threads must reach the fence position at the same time in order to continue execution. Call the await method when the thread arrives at the fence position. The latch is used to wait for the event, and the fence is used for waiting threads. Fences are used to implement protocols such as: tomorrow, all students in the 3-to-2 class meet at the school gate 8:00 and wait for others to do the next thing together, like going to a museum.

/**
 * *
 @author xiaosuda
 * @date 2018/1/8/public
class Cyclicbarriertest {
    private Cyclicbarrier cyclicbarrier = null;
    Private Exe
Related Article

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.