Since submit doesn't wait until the task completes, the executor service cannot return the result of the callable directly. Instead the executor returns a special result of type Future which can be used to retrieve the actual result at a later point in time.
After submitting the callable to the executor we first check if the future has already been finished execution via isDone. I'm pretty sure this isn't the case since the above callable sleeps for one second before returning the integer.
Calling the method get blocks the current thread and waits until the callable completes before returning the actual result Now the future is finally done and we see the following result on the console:.
Futures are tightly coupled to the underlying executor service. Keep in mind that every non-terminated future will throw exceptions if you shutdown the executor:. You might have noticed that the creation of the executor slightly differs from the previous example. We use newFixedThreadPool 1 to create an executor service backed by a thread-pool of size one.
This is equivalent to newSingleThreadExecutor but we could later increase the pool size by simply passing a value larger than one. Any call to future. In the worst case a callable runs forever - thus making your application unresponsive. You can simply counteract those scenarios by passing a timeout:. You might already have guessed why this exception is thrown: We specified a maximum wait time of one second but the callable actually needs two seconds before returning the result. Executors support batch submitting of multiple callables at once via invokeAll.
This method accepts a collection of callables and returns a list of futures. In this example we utilize Java 8 functional streams in order to process all futures returned by the invocation of invokeAll. We first map each future to its return value and then print each value to the console. If you're not yet familiar with streams read my Java 8 Stream Tutorial.
Another way of batch-submitting callables is the method invokeAny which works slightly different to invokeAll. Instead of returning future objects this method blocks until the first callable terminates and returns the result of that callable. In order to test this behavior we use this helper method to simulate callables with different durations.
The method returns a callable that sleeps for a certain amount of time until returning the given result:. We use this method to create a bunch of callables with different durations from one to three seconds. Submitting those callables to an executor via invokeAny returns the string result of the fastest callable - in that case task The above example uses yet another type of executor created via newWorkStealingPool.
Volatile If a variable is declared with the volatile keyword then it is guaranteed that any thread that reads the field will see the most recently written value. The Java memory model 4. Overview The Java memory model describes the communication between the memory of the threads and the main memory of the application. It defines the rules how changes in the memory done by threads are propagated to other threads.
It also describes which operations are atomic and the ordering of the operations. Atomic operation An atomic operation is an operation which is performed as a single unit of work without the possibility of interference from other operations.
Memory updates in synchronized code The Java memory model guarantees that each thread entering a synchronized block of code sees the effects of all previous modifications that were guarded by the same lock.
Immutability and defensive Copies 5. Immutability The simplest way to avoid problems with concurrency is to share only immutable data between threads. To make a class immutable define the class and all its fields as final. Also ensure that no reference to fields escape during construction. Therefore any field must:. Defensive Copies You must protect your classes from calling code. Collections ; import java. Threads in Java The base means for concurrency is the java. Using the Thread class directly has the following disadvantages:.
Creating a new thread causes some performance overhead. This package is described in the next section. Threads pools with the Executor Framework You find this examples in the source section in Java project called de. If you want to use one thread pool with one thread which executes several runnables you can use the Executors. ExecutorService ; import java. CompletableFuture Any time consuming task should be preferable done asynchronously. The following example demonstrates how to create a basic CompletableFuture.
CompletableFuture ; import java. You can also start a CompletableFuture delayed as of Java 9. Nonblocking algorithms Java 5. HashSet ; import java. List ; import java. Set ; import java. Callable ; import java. ExecutionException ; import java. Executors ; import java. Fork-Join in Java 7 Java 7 introduced a new parallel mechanism for compute intensive tasks, the fork-join framework.
Create first an algorithm package and then the following class. Define now the Solver class as shown in the following example coding. The API defines other top classes, e. RecursiveAction, AsyncAction. Check the Javadoc for details. Arrays ; import jsry. ForkJoinExecutor ; import jsry. ForkJoinPool ; import algorithm. Problem ; import algorithm. Deadlock A concurrent application has the risk of a deadlock. Links and Literature See License for license information.
For example, that streaming audio application must simultaneously read the digital audio off the network, decompress it, manage playback, and update its display. Even the word processor should always be ready to respond to keyboard and mouse events, no matter how busy it is reformatting text or updating the display. Software that can do such things is known as concurrent software. Standard Java threading has some downsides, however:. The JSR Concurrency Utilities framework was designed to meet the need for a high-level threading facility.
Initiated in early , the framework was formalized and implemented two years later in Java 5. Enhancements have followed in Java 6, Java 7, and the forthcoming Java 8. This two-part Java The next generation series introduces software developers familiar with basic Java threading to the Java Concurrency Utilities packages and framework.
In Part 1, I present an overview of the Java Concurrency Utilities framework and introduce its Executor framework, synchronizer utilities, and the Java Concurrent Collections package. Before you dive into this series, make sure you are familiar with the basics of threading. Start with the Java introduction to Java's low-level threading capabilities:. The Java Concurrency Utilities framework is a library of types that are designed to be used as building blocks for creating concurrent classes or applications.
These types are thread-safe, have been thoroughly tested, and offer high performance. They are further organized into a main package and a pair of subpackages:.
The Java Concurrency Utilities framework also exposes the low-level compare-and-swap CAS hardware instruction, variants of which are commonly supported by modern processors. CAS is much more lightweight than Java's monitor-based synchronization mechanism and is used to implement some highly scalable concurrent classes.
The CAS-based java. ReentrantLock class, for instance, is more performant than the equivalent monitor-based synchronized primitive.
ReentrantLock offers more control over locking. The Java Concurrency Utilities framework includes long nanoTime , which is a member of the java.
0コメント