http://www.open-open.com/bbs/view/1320131360999
As we all know, before JDK1.5, in Java in order to do business concurrency, often need to have a programmer to complete the code implementation, there are some open-source framework to provide these features, but these still do not have the functionality of the JDK is easy to use. When it comes to high-quality Java multithreading concurrent programming, in order to prevent the occurrence of such phenomena as dead jumping, such as wait (), notify () and synchronized before using Java, often need to consider performance, deadlock, fairness, Many factors, such as resource management and how to avoid the harm of thread safety, often use some more complex security policies, which aggravate the programmer's development burden. Fortunately, after the advent of JDK1.5, the Sun's Great God (Doug LEA) finally launched the Java.util.concurrent Toolkit for our poor little programmers to simplify concurrent completion. With this, developers will effectively reduce the competitive conditions (race conditions) and deadlock threads. The concurrent package solves these problems well and provides us with a more practical model of concurrent programs.
Executor: The performer of the specific runnable task.
Executorservice: A thread pool manager, with a variety of implementation classes, I'll cover some of them. We can submit the runnable,callable to the pool for dispatch.
Semaphore: A Count signal volume
Reentrantlock: A reentrant Mutex lock lock, similar in function to synchronized, but much more powerful.
Future: An interface that interacts with the runnable,callable, such as the result of a thread executing after the end of execution, and so on, and also provides a cancel termination thread.
Blockingqueue: Blocking queue.
Completionservice:executorservice, you can get the results of the thread execution
Countdownlatch: A synchronous helper class that allows one or more threads to wait until a set of operations that are executing in another thread is completed.
Cyclicbarrier: A synchronization helper class that allows a group of threads to wait for each other until a common barrier point is reached
Future:future represents the result of an asynchronous calculation.
Scheduledexecutorservice: A executorservice that can be scheduled to run after a given delay or to execute commands on a regular basis.
Next introduce
Executors Main Method Description
Newfixedthreadpool (Fixed size thread pool)
Create a thread pool that reuses a collection of fixed threads to run these threads in a shared, unbounded queue (only requests come in and wait for execution in a queue). If any thread terminates due to a failure during execution prior to shutdown, a new thread will perform subsequent tasks (if necessary) instead of it.
Newcachedthreadpool(No boundary pool, automatic thread recovery is possible)
Create a thread pool that can create new threads as needed, but reuse them when previously constructed threads are available. For programs that perform many short-term asynchronous tasks, these thread pools can often improve program performance. Calling execute reuses the previously constructed thread, if the thread is available. If an existing thread is not available, a new thread is created and added to the pool. Terminates and removes from the cache those threads that have not been used for 60 seconds. Therefore, a thread pool that remains idle for a long time does not use any resources. Note that you can use the Threadpoolexecutor construction method to create a thread pool with similar attributes but with different details, such as time-out parameters.
Newsinglethreadexecutor(Single background thread)
Create a Executor that uses a single worker thread to run the thread in a unbounded queue. (Note that if this single thread is terminated because of a failure during the execution of the shutdown, a new thread will replace it for subsequent tasks if needed). Each task is guaranteed to be executed sequentially, and no more than one thread is active at any given time. Unlike other equivalent Newfixedthreadpool (1), it is guaranteed to use other threads without reconfiguring the executing program returned by this method.
These methods return the Executorservice object, which is understood to be a thread pool.
The function of this thread pool is still quite complete. You can submit a task submit () to end the thread pool shutdown ().
Import Java.util.concurrent.ExecutorService;
Import java.util.concurrent.Executors;
public class Myexecutor extends Thread {
Private int index;
Public myexecutor (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.newfixedthreadpool (4);
for (int i=0;i<10;i++) {
Service.execute (new Myexecutor (i));
//service.submit (New Myexecutor (i));
}
System.out.println ("Submit Finish");
Service.shutdown ();
}
}
Although some information is printed, it is not very clear how this thread pool works, and we are going to increase the sleep time by 10 times times.
Thread.Sleep ((int) (Math.random () *10000));
Again, it's clear to see that only 4 threads can be executed. When a thread is executed, a new thread is executed, that is, after we commit all the threads, the thread pool waits for the last shutdown to execute. We will also find that the submitted thread is placed in a "unbounded queue". This is an ordered queue (Blockingqueue, which will be said below).
In addition, it uses the static function of executors to generate a fixed thread pool, as the name implies, thread pool threads are not freed even if it is idle.
This can result in performance problems, such as if the thread pool size is 200, and when all is done, all threads will remain in the pool, and the corresponding memory and thread transitions (while (true) +sleep loops) will increase.
If you want to avoid this problem, you must construct it directly using Threadpoolexecutor (). You can set the maximum number of threads, the minimum number of threads, and the keepalive time for idle threads, just like a common thread pool.
This is the basic usage of thread pooling.
Semaphore
A count semaphore. Conceptually, semaphores maintain a license set. If necessary, block each acquire () before the license is available, and then obtain the license. Each release () adds a license that may release a blocked fetch. However, instead of using the actual license object, Semaphore only counts the number of available licenses and takes action accordingly.
Semaphore is typically used to limit the number of threads that can access certain resources (physical or logical). For example, the following class uses semaphores to control access to a content pool:
Here is a practical situation, everyone queued to the toilet, toilets only two locations, to 10 people need to queue.
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 toilet, there is a vacancy");
}
else{
System.out.println ("Customer [" +this.id+ "] Enter the toilet, no vacancy, queue");
}
Position.acquire ();
System.out.println ("Customer [" +this.id+ "] obtain pit position");
Thread.Sleep ((int) (Math.random () *1000));
System.out.println ("Customer [" +this.id+ "]");
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 ("Use finished, need to clean up");
Position.release (2);
}
}
Reentrantlock
A reentrant mutex lock lock, which has the same basic behavior and semantics as the implicit monitor lock accessed using the Synchronized method and the statement, but is more powerful.
Reentrantlock will be owned by a thread that has recently successfully acquired a lock and has not released the lock. When the lock is not owned by another thread, the thread that called lock succeeds in acquiring the lock and returns. If the current thread already owns the lock, this method will return immediately. You can use the Isheldbycurrentthread () and Getholdcount () methods to check whether this condition occurs.
The construction method of this class accepts an optional fairness parameter.
When set to true, these locks tend to grant access to the longest waiting thread under contention for multiple threads. Otherwise, this lock will not guarantee any particular access order.
Programs that use fair locking behave as low overall throughput (that is, slow, often extremely slow) when accessed by many threads, compared to the default setting (using an unfair lock), but with little difference in obtaining locks and ensuring the equalization of lock allocations. However, it is important to note that fair locking does not guarantee the fairness of thread scheduling. Therefore, one of the many threads that use fair locking can gain multiple chances of success, which occurs when other active threads are not being processed and are not currently holding locks. Also note that the Trylock method does not use the fair setting. This method can be successful, as long as the lock is available, even if other threads are waiting.
It is recommended to always practice immediately, using a try block to invoke lock, in the previous/subsequent constructs, 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+ "acquired");
Thread.Sleep ((int) (Math.random () *1000));
}
catch (Exception e) {
E.printstacktrace ();
}
finally{
System.out.println (str+ "release");
Lock.unlock ();
}
}
}
Blockingqueue
A queue that supports two additional operations: waits for the queue to become non-empty when retrieving elements, and waits for space to become available when the element is stored.
Blockingqueue does not accept null elements. Some implementations throw NullPointerException when attempting to add, put, or offer a null element. Null is used as a warning value indicating that the poll operation failed.
The blockingqueue can be of limited capacity. It can have a remainingcapacity at any given time, exceeding this capacity, and cannot put extra elements without blocking.
Blockingqueue that do not have any internal capacity constraints always report the remaining capacity of the integer.max_value.
The Blockingqueue implementation is primarily used by the producer-consumer queue, but it also supports the Collection interface. So, for example, it is possible to use remove (x) to remove any element from the queue.
However, this operation is usually not performed effectively and can only be used on a scheduled occasion, such as when the queued information is canceled.
Blockingqueue implementations are thread-safe. All queueing methods can use internal locking or other forms of concurrency control to automatically achieve their purpose.
However, a large number of Collection operations (AddAll, Containsall, Retainall, and RemoveAll) are not necessary for automatic execution unless specifically stated in the implementation.
So, for example, AddAll (c) might fail (throw an exception) after adding only some of the elements in C.
Blockingqueue essentially does not support the use of any one of the "close" or "shutdown" actions to indicate that no more items are added.
The need for and use of this functionality has a tendency to rely on implementation. For example, a common strategy is to insert special end-of-stream or poison objects for the producer, and interpret them based on the time the consumer obtains them.
The following example shows the basic functionality of this blocking 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 < 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
will produce new asynchronous tasks that are separated from the results of the completed tasks. The task that the producer submit to perform. The consumer take the completed task,
and process their results in the order in which they were completed. For example, Completionservice can be used to manage asynchronous IO, and tasks that perform read operations are committed as part of a program or system, and
then, when the read operation is complete, other actions are performed in different parts of the program, and the Order of operations may differ from the order in which they were requested.
Typically, Completionservice relies on a single Executor to actually perform tasks, in which case the
Completionservice only manages an 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 synchronous helper class that allows one or more threads to wait until a set of operations that are performed in another thread is completed.
Initializes the countdownlatch with the given count. Because the countdown () method is called, the await method is blocked until the current count reaches 0.
After that, all the waiting threads are freed, and all subsequent calls to await are returned immediately. This behavior occurs only once-the count cannot be reset. If you need to reset the count, consider using Cyclicbarrier.
Countdownlatch is a universal synchronization tool that has many uses. The Countdownlatch initialized with Count 1 is used as a simple on/Guan device,
Or Portal: All threads that call await are waiting at the entrance until the thread that calls Countdown () opens the portal.
N-initialized Countdownlatch can cause a thread to wait until N threads complete an operation, or to wait until an operation completes N.
A useful feature of Countdownlatch is that it does not require a thread that calls the countdown method to wait until the count arrives 0 o'clock.
And before all the threads can pass, it just prevents any thread from continuing through an await.
The example is written by others, very image.
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 of the countdown lock
Final Countdownlatch begin = new Countdownlatch (1);
End of the countdown lock
Final Countdownlatch end = new Countdownlatch (10);
10 contestants
Final Executorservice exec = Executors.newfixedthreadpool (10);
for (int index = 0; index < index++) {
Final int NO = index + 1;
Runnable run = new Runnable () {
public void Run () {
try {
Begin.await ();//Always Blocked
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 method is countdown () and await (), the former is mainly a countdown, the latter is waiting for the countdown to 0, if not reached 0, only blocking wait.
Cyclicbarrier
A synchronization helper class that allows a set of threads to wait for each other until a common barrier point (common barrier points) is reached.
In programs that involve a set of fixed-size threads, these threads have to wait for each other, and cyclicbarrier is useful at this time. Because the barrier can be reused after releasing the waiting thread, it is called a cyclic barrier.
Cyclicbarrier supports an optional Runnable command, after the last thread in a set of threads arrives (but before releasing all threads),
This command runs only once at each barrier point. This barrier operation is useful if you update the shared state before continuing with all participating threads.
Example usage: Here is an example of using barrier in a parallel decomposition design, a classic example of a tour:
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 Testcyclicbarrier {
Hiking time Required: Shenzhen, Guangzhou, Shaoguan, Changsha, Wuhan
private static int[] Timewalk = {5, 8, 15, 15, 10};
Self-drive Tour
private static int[] Timeself = {1, 3, 4, 4, 5};
Tour bus
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;
This.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 Tours
Cyclicbarrier barrier = new Cyclicbarrier (3);
Executorservice exec = Executors.newfixedthreadpool (3);
Exec.submit (new tour (barrier, "Walktour", Timewalk));
Exec.submit (new tour (barrier, "Selftour", timeself));
When we comment on the code below, we find that the program is blocked and cannot continue running.
Exec.submit (new tour (barrier, "Bustour", Timebus));
Exec.shutdown ();
}
}
The most important attribute of Cyclicbarrier is the number of participants, and the best way to do this is to await (). After all the threads have called await (), it means that the threads can continue to execute, or they will wait.
Future
The future represents the result of an asynchronous calculation. It provides a way to check whether the calculation is complete, to wait for the completion of the calculation, and to retrieve the results of the calculation.
You can only use the Get method to retrieve the results after the calculation is complete and, if necessary, block this method before the calculation is complete. Cancellation is performed by the Cancel method.
Other methods are provided to determine whether the task is completed properly or canceled. Once the calculation is complete, you can no longer cancel the calculation.
If you use the future for the sake of cancellation and do not provide the available results, you can declare the Future<?> form type and return null as the result of the underlying task.
This we have seen in front of completionservice, this future function, and this can be specified as a return object at the time of the commit thread.
Scheduledexecutorservice
A executorservice that can schedule commands to run after a given delay or to be executed on a regular basis.
The schedule method creates a task with various delays and returns a task object that can be used to cancel or check execution. The Scheduleatfixedrate and Schedulewithfixeddelay methods Create and perform certain tasks that run regularly before they are canceled.
The order submitted with the Submit method of Executor.execute (java.lang.Runnable) and Executorservice is arranged by the requested 0 delay.
0 and negative delay (but not cycles) are allowed in the schedule method, and these are treated as a request for immediate execution.
All schedule methods accept relative delays and periods 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 a later date to run, you can use: Schedule (Task, Date.gettime ()-System.currenttimemillis (), timeunit.milliseconds).
Note, however, that due to network time synchronization protocol, clock drift, or other factors, the expiration date of the relative delay does not have to match the current date of the enabled task.
The Executors class provides a convenient factory approach to the Scheduledexecutorservice implementations provided in this package.
An example of this is also more popular online.
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 Scheduler = Executors.newscheduledthreadpool (2);
Final Runnable beeper = new Runnable () {
int count = 0;
public void Run () {
System.out.println (New Date () + "beep" + (++count));
}
};
Runs after 1 seconds and runs every 2 seconds
Final Scheduledfuture Beeperhandle = Scheduler.scheduleatfixedrate (beeper, 1, 2, SECONDS);
Run after 2 seconds, and then rerun each time after the last task has been run for 5 seconds
Final Scheduledfuture beeperHandle2 = Scheduler.schedulewithfixeddelay (beeper, 2, 5, SECONDS);
Closes the task after 30 seconds and closes the scheduler
Scheduler.schedule (New Runnable () {
public void Run () {
Beeperhandle.cancel (TRUE);
Beeperhandle2.cancel (TRUE);
Scheduler.shutdown ();
}
}, SECONDS);
}
}
In this way we have concurrent the more important functions have been summed up, we hope to understand that we can help.
Concurrent usage in Java