Java Concurrency Utilities: Understanding Executors, Futures, and Concurrent Collections, Exams of Programming Languages

An overview of java concurrency utilities presented at javaone by david holmes and brian goetz. It covers the rationale and goals for jsr 166, the benefits of using concurrency utilities over java's built-in concurrency primitives, and the building blocks of the concurrency utilities, including executors, futures, concurrent collections, locks, conditions, and atomic variables.

Typology: Exams

Pre 2010

Uploaded on 07/30/2009

koofers-user-b6g
koofers-user-b6g 🇺🇸

10 documents

1 / 20

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
4/14/09&
1&
Java Concurrency Utilities
Based on JavaOne talk given by
David Holmes & Brian Goetz
Overview
Rationale and goals for JSR 166
Java community process – concurrency utilities
Executors – thread pools and scheduling
Futures
Concurrent Collections
Locks, conditions and synchronizers
Atomic variables
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14

Partial preview of the text

Download Java Concurrency Utilities: Understanding Executors, Futures, and Concurrent Collections and more Exams Programming Languages in PDF only on Docsity!

Java Concurrency Utilities

Based on JavaOne talk given by

David Holmes & Brian Goetz

Overview

• Rationale and goals for JSR 166

– Java community process – concurrency utilities

• Executors – thread pools and scheduling

• Futures

• Concurrent Collections

• Locks, conditions and synchronizers

• Atomic variables

Why Concurrency Utilities

• Java’s built-in concurrency primitives -- wait(),

notify(), and synchronized – are:

• Hard to use correctly

• Easy to use incorrectly

• Too low level for many applications

• Can lead to poor performance if used incorrectly

• Leave out lots of useful concurrency constructs

Goals

• Provide efficient, correct & reusable concurrency

building blocks

• Enhance scalability, performance, readability,

maintainability, and thread-safety of concurrent

Java applications

Executor

• Standardizes asynchronous invocation

• Separates job submission from execution policy

  • anExecutor.execute(aRunnable)
  • not new Thread(aRunnable).start()

• Two code styles supported:

  • Actions: Runnables
  • Functions: Callables
  • Also has lifecycle mgmt: cancellation, shutdown, etc.

• Executor usually created via Executors factory class

  • Configures ThreadPoolExecutor
  • Customizes shutdown methods, before/after hooks, saturation policies, queuing

Executor & ExecutorService

• ExecutorService adds lifecycle management to Executor

public interface Executor { void execute( Runnable command ); } public interface ExecutorService extends Executor { void shutdown() ; List shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination( long timeout , TimeUnit unit ); // other convenience methods for submitting tasks }

Creating Executors

• Executors factory methods

public class Executors {

static ExecutorService newSingleThreadedExecutor();

static ExecutorService newFixedThreadPool( int n);

static ExecutorService newCachedThreadPool( int n);

static ScheduledExecutorService newScheduledThreadPool( int n);

// additional versions & utility methods

(Not) Executor Example

• Thread per message Web Server (no limit on thread creation)

class WebServer { public static void main( String [] args) { ServerSocket socket = new ServerSocket ( 80 ); while ( true ) { final Socket connection = socket.accept(); Runnable r = new Runnable () { public void run () {handleRequest(connection);} }; new Thread (r).start(); } } }

Future Example

• See: FutureTaskStringReverser.java

Another Future Example

• Implementing a cache with Future

public class Cache<K, V> { Map<K, Future> map = new ConcurrentHashMap(); Executor executor = Executors.newFixedThreadPool(8); public V get (final K key) { Future f = map.get(key); // null if key not found if (f == null) { Callable c = new Callable() { public V call() {// compute value associated with key}}; f = new FutureTask(c); Future old = map.putIfAbsent(key, f); // return null if key not found. put(key,f) if (old == null) // otherwise return get(key) executor.execute(f); else f = old; } return f.get(); } }

ScheduledExecutorService

• For deferred and recurring tasks, can schedule

  • Callable or Runnable to run once with a fixed delay after submission
  • Schedule a Runnable to run periodically at a fixed rate
  • Schedule a Runnable to run periodically with a fixed delay between executions

• Submission returns a ScheduledFutureTask handle which

can be used to cancel the task

• Like Timer , but supports pooling and is more robust

Concurrent Collections

• Pre-1.5 Java class libraries had few concurrent (vs

Synchronized) classes

– Synchronized collections: Hashtable, Vector, and

Collections.synchronizedXXX

  • Often required locking during iteration
  • Locking becomes is a source of contention

• Java 1.5 concurrent collections:

– Allow multiple operations to overlap

  • Some differences in semantics

Producer-Consumer Examples

• See:

– ProducerConsumerPrimitive.java (wait/notify)

– ProducerConsumerConcUtil.java (BlockingQueue)

Concurrent Collections

• ConcurrentHashMap - Concurrent (scalable) alt. to

Hashtable or Collections.synchronizedMap

  • Multiple reads can overlap each other
  • Reads can overlap writes
  • Retrieval operations reflect the results of the most recently completed update operations holding at onset of operation
  • Up to 16 writes can overlap
  • Iterators do not throw ConcurrentModificationException

• CopyOnWriteArrayList

  • Optimized for case where iteration is much more frequent than insertion or removal. E.g., event listeners

Performance Comparison

• ConcurrentHashMap vs. Collections.synchronizedMap

• See HashMapPerfTest.java

• Note: incrementCount() is not safe

Locks and Lock Support

• High-level locking interface. Adds non-blocking lock

acquistion

interface Lock { void lock(); void lockInterruptibly() throws IE; boolean tryLock(); boolean tryLock( long time ,TimeUnit unit ) throws IE; void unlock(); Condition newCondition() throws UnsupportedOperationException; }

Read/write Locks

• ReadWriteLock defines a pair of locks; one for readers;

one for writers

interface ReadWriteLock { Lock readLock(); Lock writeLock(); }

• ReentrantReadWriteLock class

  • Provides reentrant read and write locks
  • Allows writer to acquire read lock
  • Allows writer to downgrade to read lock
  • Supports “fair” and “writer preference” acquisition

Read/Write Lock Example

class RWDictionaryRWL { private final Map < String , Data > m = new TreeMap < String , Data >(); private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock (); private final Lock r = rwl.readLock (); private final Lock w = rwl.writeLock (); public Data get( String key) { r.lock(); try { return m.get(key); } finally { r.unlock(); } } public Data put( String key, Data value) w.lock(); try { return m.put(key, value); } finally { w.unlock(); } } }

Read/Write Lock Example

• See

– RWDictionary .java & RWDictionaryRWL.java

Condition

• Condition lets you wait for a condition to hold

interface Condition { void await() throws IE ; boolean await( long time, TimeUnit unit ) throws IE ; long awaitNanos( long nanosTimeout) throws IE ; void awaitUninterruptibly() boolean awaitUntil( Date deadline) throws IE ; void signal(); void signalAll(); }

Condition Example (cont.)

public Object take() throws IE { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }

Condition Example (cont.)

• Previous example in BoundedBufferCond.java

• See also: BoundedBufferPrim.java

Synchronizers

• Utilities for coordinating access and control

• CountDownLatch – allows one or more threads to

wait for a set of threads to complete an action

• CyclicBarrier – allows a set of threads to wait until

they all reach a specified barrier point

• Semaphore – Dijkstra counting semaphore , managing

some number of permits

• Exchanger – allows two threads to rendezvous and

exchange data, such as exchanging an empty buffer

for a full one

CountDownLatch

• Latching variables are conditions that once set

never change.

• Often used to start several threads, but have them

wait for a signal before continuing

• See: CountDownLatchTest.java

Exchanger

• Synch. point where two threads exchange objects

• A bidirectional SynchronizedQueue

• Each thread presents some object on entry to the

exchange() method, and receives the object

presented by the other thread on return

• See ExchangerTest.java

Atomic Variables

• Holder classes for scalars, references and fields

• Supports atomic operations

  • Compare-and-set (CAS)
  • Get and set and arithmetic (where applicable)

• Ten main classes: { int, long, ref } X { value, field, array }

  • E.g. AtomicInteger useful for counters, sequences, statistics

• Essential for writing efficient code on MPs

  • Nonblocking data structures & optimistic algorithms
  • Reduce overhead/contention updating “hot” fields

• JVM uses best construct available on platform

  • CAS, load-linked/store-conditional, locks

Atomic Variables

• See: CounterTest.java