Five things you don't know--java.util.concurrent (Part II)

Source: Internet
Author: User
Tags semaphore ibm developerworks

This is one of the 5 things series articles by Ted Neward in IBM Developerworks, and still tells us some of the application tips for the Java Concurrency Collection API, which is worth learning. (Last updated 2010.06.17)

Summary: In addition to the collection APIs that facilitate the writing of concurrent applications, Java.util.concurrent also introduces other prebuilt program components that can assist you in controlling and executing threads in multithreaded applications. Ted Neward introduces five Java programming tips from Java.util.concurrent.

The concurrent collection framework makes concurrent programming easier by providing thread-safe, well-performing data structures. In some cases, however, developers need to take a step further and consider controlling and/or adjusting the execution of threads. The whole reason for providing the java.util.concurrent package is to simplify multithreaded programming-in fact it is.
Then in the first part, this article describes multiple synchronization data structures that are higher than the core Language Infrastructure (monitor), but are not as high as they are trapped in a collection class. Once the use of these locks and plugs is known, they can be used straight away.

1. Signal Volume

In some enterprise-class systems, developers are often required to control the number of requests (threads or actions) for a particular resource. While it is entirely possible to try to write such a tuning program manually, it is easier to use the semaphore class, which handles the threading control for you, as shown in Listing 1:

Listing 1. Using semaphores to adjust threads

Importjava.util.*;
Importjava.util.concurrent.*; Public classsemapp{ Public Static voidMain (string[] args) {Runnable Limitedcall=NewRunnable () {FinalRandom Rand =NewRandom (); FinalSemaphore available =NewSemaphore (3); intCount = 0; Public voidrun () {intTime = Rand.nextint (15); intnum = count++; Try{available.acquire (); System.out.println ("Executing" + "long-running action for" + Time+ "Seconds #" +num); Thread.Sleep ( time* 1000); System.out.println ("Done with #" +Num+ "!"); Available.release (); } Catch(interruptedexception intEx) {intex.printstacktrace (); } } }; for(inti=0; i<10; i++) NewThread (Limitedcall). Start (); }}

Although the previous example has 10 threads running (which can be verified by executing the Jstack program against the Java process running Semapp), only 3 are active. The other 7 threads are saved until one of the semaphore counters is freed up. (To be precise, the semaphore class supports fetching and releasing more than one licensed thread at a time, but doing so in the scenario here is meaningless.) )

2. Countdownlatch
If the concurrency class semaphore is designed to allow "one" thread to execute at the same time, then Countdownlatch is the starting door in the race. The class holds all the threads, and when a certain condition is encountered, then Countdownlatch releases all the threads at once.

Listing 2. Countdownlatch: Let's play!

ImportJava.util.*;Importjava.util.concurrent.*;classrace{PrivateRandom Rand =NewRandom (); Private intDistance = Rand.nextint (250); PrivateCountdownlatch start; PrivateCountdownlatch finish; Privatelist<string> horses =NewArraylist<string>();  PublicRace (String names) { This. Horses.addall (arrays.aslist (names)); }         Public voidRun ()throwsinterruptedexception {System.out.println ("And the horses is stepping up to the gate"); FinalCountdownlatch start =NewCountdownlatch (1); FinalCountdownlatch finish =NewCountdownlatch (Horses.size ()); Finallist<string> places =Collections.synchronizedlist (NewArraylist<string>());  for(FinalString h:horses) {            NewThread (NewRunnable () { Public voidrun () {Try{System.out.println (H+ "stepping up to the gate");                                                Start.await (); inttraveled = 0;  while(Traveled <distance) {                            //In a 0-2 second period of time.Thread.Sleep (Rand.nextint (3) * 1000); //a horse travels 0-14 lengthstraveled + = Rand.nextint (15); System.out.println (H+ "advanced to" + traveled + "!");                        } finish.countdown (); System.out.println (H+ "crossed the finish!");                    Places.add (h); }                    Catch(interruptedexception intEx) {System.out.println ("Aborting RACE!!!");                    Intex.printstacktrace ();        }}). Start (); } System.out.println ("And they ' re off!");                Start.countdown ();        Finish.await (); System.out.println ("And we have our winners!"); System.out.println (Places.get (0) + "took the gold"); System.out.println (Places.get (1) + "Got the Silver"); System.out.println ("and" + places.get (2) + "took home the bronze."); }} Public classcdlapp{ Public Static voidMain (string[] args)throwsinterruptedexception, java.io.IOException {System.out.println ("Prepping"); Race R=NewRace ("Beverly Takes a Bath",            "Rockerhorse",            "Phineas",            "Ferb",            "Tin Cup",            "I ' m Faster Than a Monkey",            "Glue Factory Reject"            ); System.out.println ("It s a race of" + r.getdistance () + "lengths"); System.out.println ("Press Enter to run the race.");                System.in.read ();    R.run (); }}

Note in Listing 2, Countdownlatch serves two purposes: first, it frees all threads at the same time to simulate the start of the game, but then another countdownlatch simulates the end of the game. A game will have more comments, you can add Countdownlatch in the "Turn" and "half-way" points of the race, when the horses run over 1/4-way, half-way and 3/4-way.

3. Executor
The examples in Listing 1 and Listing 2 have encountered a very frustrating mistake, and you are forced to create the thread object directly. This is a troublesome way because in some JVMs it is a heavyweight task to create a thread object, so it is much better to reuse than to create a new thread. In other JVMs, however, the opposite is true: thread is very lightweight, and if you need a thread, it is much better to create it directly. Of course, if Murphy has his own approach (which he often does), no matter which method you use, it will be a mistake for some Java platform that you end up relying on.
The JSR-166 Expert Group foresaw this situation to a certain extent. Unlike having Java developers create thread instances directly, they recommend the executor interface, which is an abstraction for creating new threads. As shown in Listing 3, Executor allows you to create a thread object without using the new operator:

Listing 3. Executor

Executor exec = getanexecutorfromsomeplace (); Exec.execute (new Runnable () {  });

The main disadvantage of using Excutor is the same as the drawbacks we encounter with all object factories: Factories must come from somewhere. Unfortunately, unlike CLR,JVM, it does not come with a standard VM-scoped thread pool.
The executor class is just a common place to get a executor implementation instance, but it has only the new method (for example, in order to create a new thread pool); It has no pre-created instances. So, if you want to create and use a executor implementation that runs through the entire program, you can create a executor instance of your own. (or, in some cases, you can use the executor instance provided by the container/platform you selected.) )

Executorservice, to serve you.

The usefulness of Executorservice is that you don't have to worry about where the thread comes from, the executor interface lacks some of the features that Java developers might expect, such as starting a thread that is used to produce the result, and waits until the result occurs in a non-blocking manner. (This is a common requirement in desktop applications where users perform a UI operation that requires access to the database, and if it takes too long, it might want to cancel it before it is finished.) )
To do this, JSR-166 's experts create a more useful abstraction, the Executorservice interface, which models a factory that initiates a thread into a service so that the service can be aggregated and controlled. For example, without invoking the Execute () method once per task, Executorservice can create a collection of tasks and return a future collection that represents the next results for those tasks.

4. Scheduledexecutorservices
As good as the Executorservice interface, a specific task needs to be executed in a planned form, such as a given task at a specific time interval or at specific times. This is the responsibility of the Scheduledexecutorservice inherited from Executorservice.
If your goal is to create a "heartbeat" command, the command goes "ping" every 5 seconds. Scheduledexecutorservice will help you do this as simple as you can see in Listing 4:

Listing 4. Scheduledexecutorservice to "Ping" as planned

Importjava.util.concurrent.*; Public classping{ Public Static voidMain (string[] args) {scheduledexecutorservice ses=Executors.newscheduledthreadpool (1); Runnable Pinger=NewRunnable () { Public voidrun () {System.out.println ("Ping!");        }        }; Ses.scheduleatfixedrate (Pinger,5, 5, Timeunit.seconds); }}

What do you think? Without the annoyance of threading, if the user wants to cancel the heartbeat, do not have to worry about how to do, the foreground or the background is not showing the marked thread; All the scheduling details are left to Scheduledexecutorservice.
By the way, if the user wants to cancel the heartbeat, returning from the Scheduleatfixedrate () method is a Scheduledfuture instance that contains not only the execution result (if any), but also a cancel () method to stop the scheduled task.

5. Timeout method
Having the ability to set a certain timeout control for a blocking operation (so that you can avoid deadlocks) is one of the biggest advantages of the Java.util.concurrent class library compared to the old concurrency API, such as a monitor for locks.
These methods are almost always overloaded in int/timeunit pairs, and the int/timeunit is used to indicate how long the method waits before it jumps out and returns control to the platform. This requires the developer to do more work on it-how will recovery be done if the lock is not acquired? --but the results are almost always correct: fewer deadlocks, and more code for safer production. (For more production-ready code, see Michael Nygard's release it!)

Conclusion
Java.util.concurrent contains a number of more elegant tools, which are out of the collection framework, but better, especially those in the. Locks and. Atomic packages. Digging deeper, you'll find very useful control structures like cyclicbarrier, and even more.
Next time, we'll step into a new topic: Five things you don't know about jars.

Five things you don't know--java.util.concurrent (Part II)

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.