Here are the newly added features of Java 8:
Feature Name | Description |
---|---|
Runnable interface describes a task you want to run, perhaps
concurrently with others.
|
Runnable task = () -> { // some task to do }; ExecutorService executor = Executors.newCachedThreadPool(); // optimized for short tasks // can use exec = Executors.newFixedThreadPool(nthreads); // also int nthreads = Runtime.getRuntime().availableProcessors(); // number of processors executor.execute(task); |
Callable<V> interface (call() method) used for tasks that return value.
|
V get() throws InterruptedException, ExecutionException V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; boolean cancel(boolean mayInterruptIfRunning) boolean isCancelled() boolean isDone() |
A task may need to wait for the result of multiple subtasks. Instead of submitting
each subtask separately, you can use the invokeAll method, passing a
Collection of Callable instances. invokeAny - stops after first result is get from the task - The cancel method attempts to cancel the task. If the task isn't already running, it won't be scheduled. Otherwise, if mayInterruptIfRunning is true, the thread running the task is interrupted. - The CompletableFuture class implements the Future interface, and it provides a second mechanism for obtaining the result. You register a callback that will be invoked (in some thread) with the result once it is available. CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> { String result; Compute the result; return result; },executor); f.thenAccept((String s) -> Process the result s); //or f.whenComplete((s, t) -> {if (t == null) { Process the result s; } else { Process the Throwable t; }}); |
if(f.exists() && f.isDirectory()) { File[] allfiles = f.listFiles(); List<Callable<Long>> tasks = new ArrayList<>(); SearchFiles sf = new SearchFiles("Java"); for(File f1 : allfiles) { tasks.add(() -> { return sf.searchFile(f1.getPath()); }); } try { List<Future<Long>> results = executor.invokeAll(tasks); // This call blocks until all tasks have completed for (Future |
Visibility | |
Updates on the variables may not be visible to other threads: processors reordering instructions, omitting things not involved not aware of other threads |
|
|
Immutable classes
|
Parallel Algorithms | |
Parallel Streams The stream is broken up into segments. The filtering and counting is done on each segment, and the results are combined. You don't need to worry about the details. |
long result = coll.parallelStream().filter(s -> s.startsWith("A")).count(); long sum = IntStream.of(values).parallel().sum();Should be enough data, data should be in memory, operations should do a substantial amount of work |
Parallel Array |
Arrays.parallelSetAll(values, i -> i % 10); Arrays.parallelSort(words, Comparator.comparing(String::length)); parallelPrefix ?? |
Threadsafe Data Structures | |
java.util.concurrent package | Collections from package yelds Fail-safe iterators. They do not throw ConcurrentModificationException (as in java.util) |
ConcurrentHashMap |
|
LinkedBlockingQueue / ArrayBlockingQueue ConcurrentSkipListMap / ConcurrentSkipListSet CopyOnWriteArrayList / CopyOnWriteArraySet |
|
Atomic Counters and Accumulators | |
java.util.concurrent.atomic package AtomicLong, AtomicInteger, AtomicLongFieldUpdater, AtomicIntegerArray, AtomicReference, AtomicIntegerFieldUpdater, AtomicReferenceArray, AtomicLongArray, AtomicReferenceFieldUpdater, Boolean also LongAdder and LongAccumulator |
public static AtomicLong nextNumber = new AtomicLong(); long id = nextNumber.incrementAndGet(); public static AtomicLong largest = new AtomicLong(); // In some thread... largest.set(Math.max(largest.get(), observed)); // Error—race condition! largest.updateAndGet(x -> Math.max(x, observed)); // rightaccumulateAndGet, getAndUpdate, getAndAccumulate |
Locks | |
synchronized |
|
Can use conditions with wait() - notifyAll() (notify()) to wait for updates from other threads |
public synchronized Object take() throws InterruptedException { while (head == null) wait(); ... } public synchronized void add(Object newValue) { ... notifyAll(); } |
Threads | |
Better use Executors but can manually start Thread. Can check for interruption (if (Thread.currentThread().isInterrupted()) return; ) or interrupted while wait / sleep In latter case throws InterruptedException |
Runnable task = () -> { Thread.sleep(millis); }; Thread thread = new Thread(task); thread.start(); thread.join(millis); // stops the thread |
Thread-Local Variables | |
avoid sharing by giving each thread its own instance, using the ThreadLocal helper class |
// construct one instance per thread public static final ThreadLocal<NumberFormat> currencyFormat = ThreadLocal.withInitial(() -> NumberFormat.getCurrencyInstance()); // access formatter String amountDue = currencyFormat.get().format(total); |