Java concurrent application details Android applications also have a lot

Source: Internet
Author: User
Tags addall
 

We all know that before jdk1.5, Java usually requires programmers to complete code implementation independently. Of course, some open-source frameworks provide these functions, however, these functions are not provided by JDK for ease of use. When designing high-quality Java multi-thread concurrent programs, to prevent such phenomena as death, such as using the wait (), notify (), and synchronized before Java, every time you need to consider performance, deadlock, fairness, resource management, and how to avoid the harm caused by thread security, some complicated security policies are often used, increases the development burden of programmers. fortunately, after the appearance of jdk1.5
Lea) finally launched the java. util. Concurrent toolkit for our poor little programmers to simplify concurrency. With this, developers can effectively reduce race conditions and deadlock threads. The concurrent package solves these problems and provides us with a more practical concurrent program model.

Executor: executor of a specific runnable task.
Executorservice: A thread pool manager with multiple implementation classes. I will introduce some of them. We can submit runnable and callable to the pool for scheduling.
Semaphore: A count semaphore
Reentrantlock: A reentrant mutex lock. Its function is similar to synchronized, but it is much more powerful.
Future: it is an interface that interacts with runnable and callable. For example, a thread obtains the returned results after execution ends, and a cancel termination thread is also provided.
Blockingqueue: blocking the queue.
Completionservice: executorservice extension, which can obtain the thread execution result
Countdownlatch: A synchronization helper class that allows one or more threads to wait until a group of operations are being performed in another thread.
Cyclicbarrier: A synchronization helper class that allows a group of threads to wait for each other until it reaches a public barrier point.
Future: Future indicates the result of asynchronous calculation.
Scheduledexecutorservice: An executorservice that can be scheduled to run or periodically run after a given delay.

Next we will introduce them one by one

Main Methods of executors
Newfixedthreadpool (Fixed-size thread pool)
Create a thread pool that can reuse a set of fixed threads and run these threads in a shared, unbounded queue mode (only requests are sent and will be waiting for execution in a queue ). If any thread is terminated due to a failure during the execution before it is disabled, a new thread will execute subsequent tasks (if needed) in place of it ).

Newcachedthreadpool(The unbounded thread pool can be used for automatic thread recovery)
Create a thread pool where new threads can be created as needed, but they will be reused when previously constructed threads are available. For programs that execute many short-term asynchronous tasks, these thread pools can usually improve program performance. Calling execute will reuse the previously constructed thread (if the thread is available ). If the existing thread is not available, create a new thread and add it to the pool. Terminate and Remove unused threads from the cache for 60 seconds. Therefore, a thread pool that remains idle for a long time does not use any resources. Note: You can use the threadpoolexecutor constructor to create a thread pool with similar attributes but different details (such as timeout parameters.

Newsinglethreadexecutor(Single background thread)
Create an executor that uses a single worker thread to run this thread in an unbounded queue mode. (Note: If this single thread is terminated because of a failure during the execution before it is disabled, a new thread will execute subsequent tasks in place of it if needed ). The tasks can be executed sequentially, and no threads are active at any given time. Unlike other equivalent newfixedthreadpool (1), other threads can be used without the need to reconfigure the execution program returned by this method.

These methods return executorservice objects, which can be understood as a thread pool.
The functions of this thread pool are quite complete. You can submit the task submit () to end the thread pool Shutdown ().

package com.concurrent;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorsTest extends Thread {private int index;public ExecutorsTest(int i) {this.index = i;}public void run() {try {System.out.println("[" + this.index + "] start....");Thread.sleep((int) (Math.random() * 1000));System.out.println("[" + this.index + "] end.");} catch (Exception e) {e.printStackTrace();}}public static void main(String args[]) {ExecutorService service = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {System.out.println(" loop "+i);service.execute(new ExecutorsTest(i));}System.out.println("submit finish");service.shutdown();}}

Although some information is printed, it is not very clear. How does the thread pool work? Let's tune the sleep time by 10 times.
Thread. Sleep (INT) (math. Random () * 10000 ));

We can see that only four threads can be executed. After a thread is executed, a new thread will be executed. That is to say, after all threads are submitted, the thread pool will wait for the final shutdown after execution. We will also find that the submitted thread is put in an "unbounded queue ". This is an ordered queue (blockingqueue, which will be discussed below ).

In addition, it uses the static function of executors to generate a fixed thread pool. As the name suggests, the thread in the thread pool will not be released, even if it is an idle.
This will cause performance problems. For example, if the thread pool size is 200, after all the threads are used up, all the threads will remain in the pool, the corresponding memory and thread switching (while (true) + sleep loop) will increase.
To avoid this problem, you must use threadpoolexecutor () to construct it directly. You can set "Maximum number of Threads", "minimum number of Threads", and "keepalive time of Idle threads" like a general thread pool ".

This is the basic usage of the thread pool.

Semaphore
A count semaphore. In terms of concept, semaphores maintain a license set. If necessary, each acquire () is blocked before the license is available. Add a license for each release (), which may release a blocked recipient. However, if you do not use the actual license object, semaphore only counts the available license numbers and takes corresponding actions.

Semaphore is usually used to limit the number of threads that can access certain resources (physical or logical. For example, the following classes use semaphores to control access to the content pool:

Here is the actual situation. We queue up for the toilet. There are only two locations for the toilet. 10 people need to queue up.

Import Java. util. concurrent. executorservice; import Java. util. concurrent. executors; import Java. util. concurrent. semaphore; public class mysemaphore extends thread {semaphore position; private int ID; Public mysemaphore (int I, semaphore s) {This. id = I; this. position = s;} public void run () {try {If (position. availablepermits ()> 0) {system. out. println ("customer [" + this. ID + "] enter the restroom, there is a vacant space");} else {system. out. println ("customer [" + this. ID + "] enter the restroom, no space available, queuing");} position. acquire (); system. out. println ("customer [" + this. ID + "] Get slot"); thread. sleep (INT) (math. random () * 1000); system. out. println ("customer [" + this. ID + "] used"); position. release ();} catch (exception e) {e. printstacktrace () ;}} public static void main (string ARGs []) {executorservice list = executors. newcachedthreadpool (); semaphore position = new semaphore (2); For (INT I = 0; I <10; I ++) {list. submit (New mysemaphore (I + 1, position);} List. shutdown (); position. acquireuninterruptibly (2); system. out. println ("cleaned after use"); position. release (2 );}}

Reentrantlock
A reentrant mutex lock, which has the same basic behavior and semantics as the implicit monitor lock accessed by the Synchronized Method and statement, but is more powerful.

The reentrantlock will be held by the thread that has recently been successfully locked and has not been released. When the lock is not owned by another thread, the thread that calls the lock will successfully obtain the lock and return it. If the current thread already has this lock, this method will return immediately. You can use the isheldbycurrentthread () and getholdcount () methods to check whether this situation has occurred.

Such constructor accepts an optional fair parameter.
When it is set to true, these locks tend to grant the access permission to the thread with the longest wait time under the competition of multiple threads. Otherwise, the lock will not guarantee any specific access order.
Compared with the default setting (using unfair locks), the program with fair locks performs a very low overall throughput (that is, the speed is very slow, often extremely slow) during access to many threads ), however, the time difference between obtaining a lock and ensuring a balanced lock allocation is small. However, fair locking does not guarantee the fairness of thread scheduling. Therefore, one of the many threads that use fair locks may have multiple chances of success, which occurs when other active threads are not processed and are not currently holding the lock. Note that the irregular trylock method does not use fair settings. This method is successful even if other threads are waiting and the lock is available.

We recommend that you always practice it immediately and use try block to call lock. In the previous/subsequent construction, the most typical code is as follows:

Class X {private final reentrantlock lock = new reentrantlock ();//... public void M () {lock. lock (); // block until condition holds try {//... method body} finally {lock. unlock () }}my example: Import Java. util. concurrent. executorservice; import Java. util. concurrent. executors; import Java. util. concurrent. locks. reentrantlock; public class myreentrantlock extends thread {testreentrantlock lock; private int ID; Public myreentrantlock (int I, testreentrantlock test) {This. id = I; this. lock = test;} public void run () {lock. print (ID);} public static void main (string ARGs []) {executorservice service = executors. newcachedthreadpool (); testreentrantlock lock = new testreentrantlock (); For (INT I = 0; I <10; I ++) {service. submit (New myreentrantlock (I, lock);} service. shutdown () ;}} class testreentrantlock {private reentrantlock lock = new reentrantlock (); Public void print (INT Str) {try {lock. lock (); system. out. println (STR + "get"); thread. sleep (INT) (math. random () * 1000);} catch (exception e) {e. printstacktrace ();} finally {system. out. println (STR + "release"); lock. unlock ();}}}

Blockingqueue
Two additional operations are supported: waiting for the queue to become non-empty when retrieving elements, and waiting for space to become available when storing elements.

Blockingqueue does not accept null elements. When you try to add, put, or offer a null element, some implementations will throw nullpointerexception. Null is used as a warning value to indicate that the poll operation fails.

Blockingqueue can be a limited capacity. It can have a remainingcapacity at any given time, beyond which additional elements cannot be put without interruption.
Blockingqueue without any internal capacity constraints always reports the remaining capacity of integer. max_value.

Blockingqueue is mainly used for producer-user queues, but it also supports the collection interface. Therefore, for example, it is possible to remove any element from the queue using remove (X.
However, such operations are generally not executed effectively and can only be used occasionally in a planned manner, for example, when queuing information is canceled.

Blockingqueue implementation is thread-safe. All queuing methods can be automatically achieved using internal locking or other forms of concurrency control.
However, a large number of collection operations (addall, containsall, retainall, and removeall) do not require automatic execution unless otherwise specified in the implementation.
Therefore, for example, after only some elements in C are added, addall (c) may fail (throwing an exception ).

Blockingqueue does not support any "close" or "shutdown" operation to indicate that no items are added.
The demand and use of such features are dependent on implementation. For example, a common policy is to insert a special end-of-stream or poison object to the producer and explain the Objects Based on the time the user obtains them.

The following example demonstrates the basic functions of this blocked queue.

import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;public class MyBlockingQueue extends Thread {public static BlockingQueue<String> queue = new LinkedBlockingQueue<String>(3);private int index;public MyBlockingQueue(int i) {this.index = i;}public void run() {try {queue.put(String.valueOf(this.index));System.out.println("{" + this.index + "} in queue!");} catch (Exception e) {e.printStackTrace();}}public static void main(String args[]) {ExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {service.submit(new MyBlockingQueue(i));}Thread thread = new Thread() {public void run() {try {while (true) {Thread.sleep((int) (Math.random() * 1000));if (MyBlockingQueue.queue.isEmpty())break;String str = MyBlockingQueue.queue.take();System.out.println(str + " has take!");}} catch (Exception e) {e.printStackTrace();}}};service.submit(thread);service.shutdown();}}

------------------- Execution result -----------------
{0} in queue!
{1} in queue!
{2} in queue!
{3} in queue!
0 has take!
{4} in queue!
1 has take!
{6} in queue!
2 has take!
{7} in queue!
3 has take!
{8} in queue!
4 has take!
{5} in queue!
6 has take!
{9} in queue!
7 has take!
8 has take!
5 has take!
9 has take!

-----------------------------------------

Completionservice

Services that separate the production of new asynchronous tasks from those that use the results of completed tasks. Task executed by the producer submit. The user takes completed tasks,
And process the results in the order they are completed. For example, completionservice can be used to manage asynchronous Io, and the task for executing read operations is submitted as part of a program or system,
Then, when the read operation is completed, other operations will be performed in different parts of the program. The operation execution sequence may be different from the requested sequence.

Generally, completionservice depends on a separate executor to actually execute tasks. In this case,
Completionservice only manages one internal Completion queue. The executorcompletionservice class provides an implementation of this method.

import java.util.concurrent.Callable;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class MyCompletionService implements Callable<String> {private int id;public MyCompletionService(int i) {this.id = i;}public static void main(String[] args) throws Exception {ExecutorService service = Executors.newCachedThreadPool();CompletionService<String> completion = new ExecutorCompletionService<String>(service);for (int i = 0; i < 10; i++) {completion.submit(new MyCompletionService(i));}for (int i = 0; i < 10; i++) {System.out.println(completion.take().get());}service.shutdown();}public String call() throws Exception {Integer time = (int) (Math.random() * 1000);try {System.out.println(this.id + " start");Thread.sleep(time);System.out.println(this.id + " end");} catch (Exception e) {e.printStackTrace();}return this.id + ":" + time;}}

Countdownlatch

A synchronization helper class that allows one or more threads to wait until a group of operations are performed in another thread.

Initialize countdownlatch with the given count. Because the countdown () method is called, The await method will be blocked until the current count reaches zero.
Then, all the waiting threads will be released, and all subsequent calls of await will be returned immediately. This occurs only once-The Count cannot be reset. To reset the count, consider using javasicbarrier.

Countdownlatch is a common synchronization tool that has many uses. Use countdownlatch initialized by count 1 as a simple on/off lock,
Or entry: Before the entry is opened by calling the countdown () thread, all the threads that call await are waiting at the entrance.
Using the countdownlatch initialized by N enables a thread to wait until n threads complete an operation, or to wait until N operations are completed.

A useful feature of countdownlatch is that it does not require the thread that calls the countdown method to continue until the count reaches zero,
Before all threads can pass, it only blocks any threads from continuing to pass an await.
The example below is written by others and is very vivid.

Import Java. util. concurrent. countdownlatch; import Java. util. concurrent. executorservice; import Java. util. concurrent. executors; public class testcountdownlatch {public static void main (string [] ARGs) throws interruptedexception {// start the final countdownlatch begin = new countdownlatch (1 ); // final countdownlatch end = new countdownlatch (10); // ten contestants final executorservice exec = executors. newfixedthreadpool (10); For (INT Index = 0; index <10; index ++) {final int NO = index + 1; runnable run = new runnable () {public void run () {try {begin. await (); // always blocks thread. sleep (long) (math. random () * 10000); system. out. println ("no. "+ NO +" arrived ");} catch (interruptedexception e) {} finally {end. countdown () ;}}; exec. submit (run);} system. out. println ("Game start"); begin. countdown (); end. await (); system. out. println ("game over"); Exec. shutdown ();}}

Countdownlatch the most important methods are countdown () and await (). The former is mainly the reciprocal, and the latter is waiting for the reciprocal to 0. If it does not reach 0, it will only wait for blocking.

Cyclicbarrier

A synchronization helper class that allows a group of threads to wait for each other until a common barrier point is reached ).
In a program involving a set of fixed threads, these threads must wait for each other from time to time. In this case, javasicbarrier is useful. This barrier can be reused after the waiting thread is released, so it is called a circular barrier.

Javasicbarrier supports an optional runnable command. After the last thread in a group of threads arrives (but before all threads are released ),
This command runs only once at each barrier point. This barrier operation is useful if the sharing status is updated before all participating threads continue.

Example usage: The following is an example of using barrier in parallel decomposition design. It is a classic tour group example:

Import Java. text. simpledateformat; import Java. util. date; import Java. util. concurrent. brokenbarrierexception; import Java. util. concurrent. cyclicbarrier; import Java. util. concurrent. executorservice; import Java. util. concurrent. executors; public class testpolicicbarrier {// time required for hiking: Shenzhen, Guangzhou, Shaoguan, Changsha, wuhanprivate static int [] timewalk = {5, 8, 15, 15, 10 }; // self-driving Private Static int [] Timeself = {1, 3, 4, 4, 5}; // coach Private Static int [] timebus = {2, 4, 6, 6, 7 }; static string now () {simpledateformat SDF = new simpledateformat ("HH: mm: SS"); Return SDF. format (new date () + ":";} static class tour implements runnable {private int [] times; private cyclicbarrier barrier; private string tourname; public tour (cyclicbarrier barrier, string tourname, int [] times) {This. times = times; th Is. tourname = tourname; this. barrier = barrier;} public void run () {try {thread. sleep (Times [0] * 1000); system. out. println (now () + tourname + "reached Shenzhen"); barrier. await (); thread. sleep (Times [1] * 1000); system. out. println (now () + tourname + "reached Guangzhou"); barrier. await (); thread. sleep (Times [2] * 1000); system. out. println (now () + tourname + "reached Shaoguan"); barrier. await (); thread. sleep (Times [3] * 1000); system. out. println (now () + tourname + "reached Changsha"); barrier. await (); thread. sleep (Times [4] * 1000); system. out. println (now () + tourname + "reached Wuhan"); barrier. await ();} catch (interruptedexception e) {}catch (brokenbarrierexception e) {}} public static void main (string [] ARGs) {// three tour groups: cyclicbarrier barrier = new cyclicbarrier (3); executorservice exec = executors. newfixe Dthreadpool (3); Exec. submit (New Tour (barrier, "partition tour", timewalk); Exec. submit (New Tour (barrier, "selftour", timeself); // when we comment out the following code, we will find that the program is blocked and cannot continue running. Exec. Submit (New Tour (barrier, "bustour", timebus); Exec. Shutdown ();}}

The most important attribute of javasicbarrier is the number of participants, and the most important method is await (). When await () is called by all threads, it indicates that these threads can continue to run; otherwise, they will wait.

Future

Future indicates the result of asynchronous calculation. It provides a method to check whether the computation is complete, waiting for the computation to complete and retrieving the computation results.
After calculation, you can only use the get method to retrieve results. If necessary, you can block this method before calculation. The cancel method is used to cancel the operation.
Other methods are provided to determine whether the task is completed normally or canceled. Once the computation is completed, the computation cannot be canceled.
If you use future for cancellation but do not provide available results, you can declare future <?> Format type, and return null as the result of the basic task.

We have seen this in the previous completionservice, the future function, and this can be designated as a return object when submitting the thread.

Scheduledexecutorservice

An executorservice that can be scheduled to run or periodically executed after a given delay.

The schedule method creates tasks with various delays and returns a task object that can be used to cancel or check execution. The scheduleatfixedrate and schedulewithfixeddelay methods are used to create and execute some tasks that have been regularly run before cancellation.

The commands submitted using the submit method of executor.exe cute (Java. Lang. runnable) and executorservice are arranged by zero latency of the request.
The schedule method allows a latency of 0 and a negative number (but not a cycle), and treats these requests as an immediate execution.

All schedule methods accept relative latency and period as parameters, rather than absolute time or date. It is easy to convert the absolute time represented by date into the required form.
For example, to schedule running on a later date, you can use: Schedule (task, date. gettime ()-system. currenttimemillis (), timeunit. milliseconds ).
However, due to the existence of the network time synchronization protocol, clock drift, or other factors, the expiration date of the relative delay does not need to be consistent with the current date of the task to be enabled.
The executors class provides a convenient factory method for implementing scheduledexecutorservice provided in this package.

The following example is also popular on the Internet.

Import static Java. util. concurrent. timeunit. seconds; import Java. util. date; import Java. util. concurrent. executors; import Java. util. concurrent. scheduledexecutorservice; import Java. util. concurrent. scheduledfuture; public class testscheduledthread {public static void main (string [] ARGs) {final scheduledexecutorservice schedors = executors. newscheduledthreadpool (2); Final runnable beeper = new runnable () {int COUNT = 0; Public void run () {system. out. println (new date () + "beep" + (++ count) ;}}; // run after 1 second, and run final scheduledfuture beeperhandle = schedure every 2 seconds. scheduleatfixedrate (beeper, 1, 2, seconds); // run after 2 seconds, and re-run final scheduledfuture beeperhandle2 = scheduler every time after the last task is run. schedulewithfixeddelay (beeper, 2, 5, seconds); // close the task 30 seconds later and disable schedulerscheday. schedule (New runnable () {public void run () {beeperhandle. cancel (true); beeperhandle2.cancel (true); schedcel. shutdown () ;}, 30, seconds );}}

Article: http://www.cnblogs.com/aurawing/articles/1887056.html

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.