Futuretask in Java Multi-threading and location of formal environmental problems __java

Source: Internet
Author: User
Tags cpu usage

Through the Futuretask source we can see the Futurentask class implements the Runnablefuture interface, inherits the Runnable and the future interface.
public class Futuretask implements Runnablefuture
Public interface Runnablefuture extends Runnable, Future
Futuretask can be delivered to executor or executed directly by the calling thread (Futuretask.run ()). Depending on the timing of the Futuretask.run () method, Futuretask mainly has the following states:
1, not started. Futuretask is not started until the Futuretask.run () method has not been executed. This futuretask is not started until a futuretask is created and the Futuretask.run () method is not executed.
2, has been started. The Futuretask is in the started state while the Futuretask.run () method is being executed.
3, has been completed. The Futuretask.run () method completes normally after execution, or is canceled (Futuretask.cancel (...). ), or an exception is thrown when the Futuretask.run () method is executed, and the Futuretask is in the completed state.
Here we take a look at the transformation process diagram of these states:

Executing the Futuretask.get () method causes the calling thread to block when Futuretask is in an open or started state, and executes Futuretask.get () when Futuretask is in the completed state. method causes the calling thread to immediately return the result or throw an exception.
When Futuretask is in an open state, executing the Futuretask.cancel () method will cause the task to never be executed, and when Futuretask is in the started state, The execution of the Futuretask.cancel (true) method attempts to stop the task in a way that interrupts the execution of this task thread, and when Futuretask is in a started state, the execution of the Futuretask.cancel (false) method will not affect the thread that is executing the task (let Task is completed), and when Futuretask is in the completed state, execute Futuretask.cancel (... Method will return false.
Now let's take a look at the Get and cancel execution process
Futuretask Use

Futuretask can be executed through executor, or it can return a futuretask through Executorservice.submit, and then execute various methods within Futuretask.
You can use Futuretask when a thread needs to wait for another thread to finish executing a task before it can continue. Suppose multiple threads perform several tasks, and each task can only be executed once. When multiple threads try to perform the same task at the same time, only one thread is allowed to perform the task, and other threads need to wait for the task to execute before continuing

public class Futuretasktest {private final concurrentmap<object,future<string>> Taskcache = n

    EW concurrenthashmap<object,future<string>> (); public string Executiontask (final String taskname) throws executionexception,interruptedexception{fo R (;;)
            {future<string> Future = Taskcache.get (taskname); if (future = = null) {callable<string> task = new callable<string> () {@Overr
                    IDE Public String call () throws Exception {return taskname;
                }

                };
                futuretask<string> futuretask = new futuretask<string> (Task);
                If a taskname is present, it is not placed in the map, and the return value is the futuretask future = Taskcache.putifabsent (TaskName, Futuretask);
                    if (future = = null) {future = Futuretask;
    Futuretask.run ();            try {return futuretask.get ();
                    catch (Exception e) {taskcache.remove (TaskName, future);
                E.printstacktrace (); }
            }
        }
    }
}

Convert the above code to a flowchart as follows:

When two threads try to perform the same task at the same time, if thread 1 executes putifabsent thread 2 performs a get fetch task, then thread 2 waits in Future.get () until thread 1 Thread 2 can be returned from (Futuretask.get ()) after Futuretask.run () has been executed. Futuretask Realization Principle

The implementation of Futuretask is based on Abstractqueuedsynchronizer (AQS). Many of the blocking classes in the java.util.concurrent, such as Reentrantlock, are implemented based on AQS. AQS is a synchronization framework that provides a common mechanism for atomicity to manage synchronization states, block and wake threads, and maintain queues for blocked threads. Aqs is widely used in JDK 6, and the Synchronizer based on AQS implementation includes: Reentrantlock, Semaphore, Reentrantreadwritelock, Countdownlatch, and Futuretask.
Each synchronizer based on the AQS implementation will contain two types of operations, the first being at least one acquire operation. This operation blocks the calling thread unless the thread is allowed to continue execution until the AQS state. The Futuretask acquire operation is called by the Get ()/get (Long Timeout,timeunit) method.
The other is at least one release operation. This operation changes the state of the Aqs, and the changed state allows one or more blocked threads to be unblocked. Futuretask release operations include the Run () method and Cancel (...). Method Based on the principle of "compound precedence over inheritance", Futuretask declares an internally private subclass of Aqs that inherits from the Futuretask, and calls to all public methods are delegated to the inner subclass. Aqs is provided to Futuretask's inner subclass sync as the underlying class of the template method pattern, which requires only the methods of state checking and state updating that control the acquisition and release operations of the Futuretask. Specifically, sync implements the Aqs tryacquireshared (int) method and the tryreleaseshared (int) method, in which sync checks and updates the sync state by both methods.
Sync is the internal private class of Futuretask, which inherits from Aqs. Creating a futuretask creates an internal private member object Sync,futuretask all of the public methods are directly delegated to the internal private sync. The Futuretask.get () method invokes the aqs.acquiresharedinterruptibly (int arg) method, which executes the following procedure.
1. Call the aqs.acquiresharedinterruptibly (int arg) method, which first recalls the tryacquireshared () method implemented in the subclass sync to determine whether the acquire operation can succeed. The acquire operation can succeed on the condition that state is cancelled for execution completion status ran or canceled, and runner is not null.
2. If successful, the Get () method returns immediately. If it fails, the thread waits in the queue to wait for the other thread to perform the release operation.
3, when other threads perform release operations (such as Futuretask.run () or Futuretask.cancel (...). ) After the current thread is awakened, the current thread executes tryacquireshared () again () returns a positive value of 1, the current thread leaves the thread waiting for the queue and wakes up its successor thread (this will produce a cascade wakeup effect, which is described later).
4. Returns the result of the calculation or throws an exception at the end.
Let's take a look at the Futuretask.run () execution process
1. Perform the tasks specified in the constructor (Callable.call ()).
2. Update the synchronization state atomically (call aqs.compareandsetstate (int expect,int update), set state to execute completion status ran). If the atomic operation succeeds, set the return value of Callable.call () to the value of the variable that represents the result of the calculation, and then call aqs.releaseshared (int arg).
3, aqs.releaseshared (int arg) first recalls tryreleaseshared (ARG) implemented in the subclass sync to perform a release operation (set the thread that runs the task runner to null, but returns TRUE) ; aqs.releaseshared (int arg), and then wakes the thread to wait for the first thread in the queue.
4, call Futuretask.done ().
When the Futuretask.get () method is executed, if futuretask is not in execution ran or canceled state cancelled, the current execution thread waits in the queue for the AQS thread (see Threads A, B, C, and D below). When a thread executes the Futuretask.run () method or Futuretask.cancel (...). method, wakes the thread to wait for the queue's first
Threads (see thread E, Wake thread A) as shown in the following illustration.

Assuming that the futuretask is in an open or started state at the start, the waiting queue has 3 threads (A, B, and C) waiting. At this point, thread D executes the Get () method, which causes thread D to wait in the queue. When thread E executes the run () method, the first thread A in the queue is awakened. After thread A is awakened, it first deletes itself from the queue, then wakes up its successor thread B, and the last thread a returns from the Get () method. Threads B, C, and D repeat the process flow of a thread. In the end, all threads waiting in the queue are cascaded awakened and returned from the Get () method.multi-threaded formal environmental problem positioning

Multithreading problems are often difficult to locate, the main brain simulation of a variety of possible problems, and then through the analysis of logs, System State and dump thread, we introduce several ways to facilitate our positioning problems. use the top command on the Linux command line to view the status of each process


Our program is Java application, so we just need to focus on the command is Java performance data, commands to start the current process, in this line of Java process can see CPU utilization is >100%, don't worry, This is the CPU utilization for all cores of the current machine. use Top's interactive command number 1 to view performance data for each CPU


The command line shows CPU3, which is a 4-core virtual machine with an average of less than 3% per CPU utilization. If CPU utilization 100% is shown here, it is quite possible that a dead loop is written in the program
Parameter description
US:% User space CPU usage
1.0% SY: Kernel footprint CPU%
0.0% ni: User process space has changed the priority process to consume CPU percent
98.7% ID: Free CPU percent
0.0% wa: Waiting for input/output CPU time percent view performance information for each thread using the top interaction command H


Here we need special major three cases:
1, a thread CPU utilization has been 100%, then the thread is likely to have a dead loop, we can write down this PID.
2, where a thread has been in Top 10, indicates that this thread may have a performance problem.
3, several threads with high CPU utilization are constantly changing, indicating that a thread is not causing the CPU to be too high.
If it is the first case, it may be the GC, you can use the Jstat command to look at the GC situation, to see if it is due to persistent generation or old age, resulting in full GC, resulting in high CPU utilization
can also dump the thread down to see which thread, What code is executed causes high CPU utilization. Execute the following command to dump the thread into the file Dump.test.log. Execute the following command.

Sudo-u admin/opt/usr/java/bin/jstack 31177 >/home/fuyuwei/dump.test.log
"http-0.0.0.0-7001-97" Daemon prio= Ten tid=0x000000004f6a8000 nid=0x555e in Object.
Wait () [0x0000000052423000]
Java.lang.Thread.State:WAITING (in Object Monitor) at
java.lang.Object.wait ( Native method)
-Waiting On (a org.apache.tomcat.util.net.aprendpoint$worker) at
java.lang.Object.wait ( object.java:485) at
org.apache.tomcat.util.net.aprendpoint$worker.await (aprendpoint.java:1464)
-Locked ( A org.apache.tomcat.util.net.aprendpoint$worker) at
Org.apache.tomcat.util.net.aprendpoint$worker.run ( aprendpoint.java:1489) at
Java.lang.Thread.run (thread.java:662)

The Dump thread ID (NID) is hexadecimal, and the thread ID we see with the top command is decimal, so convert the system with the printf command. And then use the hexadecimal ID to find the corresponding thread in the dump.
For example, we navigate to pid=1234 with top and then turn to hexadecimal

printf "%x\n" 1234
4d2

Here we will simply introduce these several ways.

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.