310 likes | 551 Views
Java Concurrency. by Eric Burke burke.eric@gmail.com. i ++ is not Atomic. AtomicInteger. final AtomicInteger tally = new AtomicInteger (); int a = tally.get (); int b = tally.getAndIncrement (); int c = tally.incrementAndGet (); int d = tally.getAndAdd (20); etc….
E N D
Java Concurrency by Eric Burke burke.eric@gmail.com
AtomicInteger final AtomicInteger tally = new AtomicInteger(); int a = tally.get(); int b = tally.getAndIncrement(); int c = tally.incrementAndGet(); int d = tally.getAndAdd(20); etc… Useful as a mutable type wrapper
Atomic Variables java.util.concurrent.atomic • AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference, etc… • set(), get(), incrementAndGet(), getAndIncrement(), addAndGet(int n), etc… • Enable nonblocking algorithms • Use atomic machine instructions • compare-and-swap
Swing • Components and models arethread-confined • SwingUtilities • invokeLater(Runnable) • invokeAndWait(Runnable) • isEventDispatchThread() • SwingWorker (Java 6)
SwingWorker final JLabel label; class MeaningOfLifeFinder extendsSwingWorker<String, Object> { public String doInBackground() { return findTheMeaningOfLife(); } protected void done() { try { label.setText(get()); } catch (Exception ignore) { } } } (new MeaningOfLifeFinder()).execute(); Example from SwingWorkerJavaDocs
SwingWorker Demo • Run DemoSwingWorker • Code Review
CopyOnWriteArraySet private final Set<ActionListener> listeners = new CopyOnWriteArraySet<ActionListener>(); public void addActionListener(ActionListener l) { listeners.add(l); } public void removeActionListener(ActionListener l) { listeners.remove(l); } private void notifyListeners(ActionEvent e) { for (ActionListener l : listeners) { l.actionPerformed(e); } }
ThreadFactory • Assign names to your threads • Better than “new Thread” • daemon status • priority • Provide an UncaughtExceptionHandler
ThreadFactoryExample DemoThreadFactory
Risks • Daemon threads • finally blocks do not execute at VM shutdown • ThreadLocal with thread pool • leak, leak, leak
Code Smells? • Abusing Thread.sleep() • Using SwingUtilities.invokeLater() for wrong reasons • GUI painting artifacts
Pre-Java 5 • Two ways to coordinate access to shared data: • synchronized, volatile • Problems with synchronized: • Cannot interrupt a thread that is waiting on a lock • Cannot attempt to acquire a lock without possibly blocking forever • Intrinsic locks must be released in the same block of code in which they were acquired
Lock Interface • Similar to intrinsic locking • provides mutual exclusion • same memory-visibility guarantees • Advantages • solves problems listed on previous slide
Lock Example Lock lock = new ReentrantLock(); lock.lock(); try { …do stuff here } finally { lock.unlock(); } Example 13.2 from “Java Concurrency in Practice” • Instead of lock(), you can call one of these: • booleantryLock() • booleantryLock(long timeout, TimeUnit unit) • lockInterruptibly()
Read-Write Locks • Multiple simultaneous readers • Only one writer • Great for “read-mostly” data structures See NameIdLookup.java
Immutability • Immutable objects are thread-safe • Does this pose a problem for modern POJO frameworks like Spring, JPA, Hibernate, and others? I use “final” wheneverI can
Exception Handling • Walk through the BlowUp demo
Interruption (1) public void run() { while (!Thread.currentThread().isInterrupted()) { …do something important } } Be careful: Calling Thread.interrupted() Clears the Flag
Interruption (2) Blocks public void run() { try { Message msg = myQueue.take(); …do something important } catch (InterruptedException ignored) { // let this thread complete } }
Interruption (3) void copy(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[BUFFER_SIZE]; intlen; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException(); } } }
Some Interruption Tips • Interrupt a thread like this: • myThread.interrupt() • Thread.currentThread().interrupt() • myExecutorService.shutdownNow() • When looping, check if interrupted • Such as when downloading large files • When interrupted • Let your thread end, or propagate an InterruptedException
CountDownLatch • java.util.concurrent.CountDownLatch • constructor accepts a count await() countDown() Block until count reaches 0 Decrement the count See LatchDemo
CyclicBarrier • Similar to CountDownLatch • But can be reused over and over • Initialize with a count • Each thread calls await() • All released when count is reached See CyclicBarrierDemo
BlockingQueue • Useful for producer/consumer • Producer Thread(s) • queue.put(obj) • blocks until the queue has room • Consumer Thread(s) • queue.take() • blocks until an object is available in the queue See DonutDemo
ConcurrentHashMap • A thread-safe Map implementation • But not completely synchronized like Hashtable • Uses a technique called lock striping • Array of 16 locks internally • Up to 16 concurrent writers • ConcurrentMap<K,V> interface • V putIfAbsent(K key, V value) • boolean remove(K key, V value) • boolean replace(K key, V oldValue, V newValue) • V replace(K key, V newValue)