Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Threads & Concurrency

Similar presentations


Presentation on theme: "Java Threads & Concurrency"— Presentation transcript:

1 Java Threads & Concurrency
All material not from online sources/textbook copyright © Travis Desell, 2012

2 Online Reference sential/concurrency/

3 Threads Threads are Objects too!
ang/Thread.html You can also use Executors, but more on those later.

4 Thread Objects Thread has an empty run() method, you can override it
public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new HelloThread()).start(); Thread has an empty run() method, you can override it Starting the thread will run the run() method and immediately return -- it does not block like other methods

5 The Runnable Interface
public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new Thread(new HelloRunnable())).start(); Similar to a Thread object, except an interface Use it to create new threads that need to extend another class

6 Pausing a Thread public class SleepMessages { public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds Thread.sleep(4000); //Print a message System.out.println(importantInfo[i]); } The sleep method pauses a thread for (roughly -- OS dependent) that many milliseconds If another thread interrupts a sleeping thread, the sleep method will throw an InterruptedException

7 Interrupting a Thread for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds try { Thread.sleep(4000); } catch (InterruptedException e) { //We've been interrupted: no more messages. return; } //Print a message System.out.println(importantInfo[i]); Will print a message every four seconds until interrupted or there are no more messages

8 Interrupting a Thread 2 for (int i = 0; i < inputs.length; i++) { heavyCrunch(inputs[i]); if (Thread.interrupted()) { //We've been interrupted: no more crunching. return; } What if your methods don’t throw InterruptedException? Thread.interrupted() returns true if the current thread has been interrupted. A subsequent call to Thread.interrupted() will return false unless the thread was interrupted again. It may be better to throw a new InterruptedException instead of returning.

9 “Joining” a Thread t.join(); will wait for the thread t to complete
t.join(millis); will wait at most millis ms (again roughly) for t to complete if interrupted, will throw an InterruptedException

10 Synchronization Threads communicate by sharing access to fields and methods of objects they reference This can lead to some big problems

11 Thread Interference the c++ statement: the c-- statement: retrieve c
class Counter { private int c = 0; public void increment() { c++; } public void decrement() { c--; } public int value() { return c; } the c++ statement: the c-- statement: retrieve c increment c decrement c store value

12 Thread Interference 2 What if two threads use the same Counter?
Thread A calls increment, Thread B calls decrement Thread A: retrieve c (A’s c == 0) Thread B: retrieve c (B’s c == 0) Thread A: increment c (A’s c = 1) Thread B: decrement c (B’s c = -1) Thread A: store c (stores 1) Thread B: store c (stores -1)

13 Thread Interference 3 What went wrong?
Performing operations on the same memory with multiple threads at the same time can cause some very nasty bugs

14 Memory Consistency Thread A and B share a reference to counter:
int counter = 0; Thread A increments counter: counter++; After, B prints out counter: System.out.println(counter); B may print out 0! Due to Threading implementations and hardware, A and B may not necessarily be working on the same memory.

15 Happens-Before Happens-Before relationships guarantee some statements happen before others Thread.join() and Thread.start() are two examples More Reading: urrent/package-summary.html#MemoryVisibility

16 Synchronized Methods public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } It is not possible for threads to interleave/interfere on a synchronized method -- only one thread may be executing the code synchronized on an object at a time, others will wait Synchronized methods establish happens-before relationships on subsequent method invocations Having a synchronized method is like wrapping a mutex around the method. Constructors cannot be synchronized -- so be careful

17 Synchronized Blocks Will only synchronize the block on this
public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); Will only synchronize the block on this

18 Synchronized Blocks 2 Allows fine grained synchronization
public class MsLunch { private long c1 = 0, c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } Allows fine grained synchronization Be careful: if c1 and c2 were objects that shared references to other objects, they could interleave in other methods

19 Reentrant Synchronization
Using synchronized gives threads a lock on a section of code A thread cannot execute code another thread has a lock on A thread can get a lock on code it already has a lock on, this is reentrant synchronization Without this, it would be much easier to create deadlock (ex., a synchronized method calls itself)

20 Atomic Accesses An atomic action happens all at once (therefore they can’t interleave) Reads and write for reference variables and primitive (except long and double) are atomic variables declared volatile also have atomic read and write (even long or double) writing to a volatile variable also sets up happens-before dependencies to subsequent reads of that variable

21 Liveness A concurrent applications ability to execute in a timely manner (or at all) is its ‘liveness’ Deadlock, starvation and livelock are concurrent programming issues which prevent liveness

22 Deadlock public class Deadlock { static class Friend {
private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public synchronized void bowBack(Friend bower) { System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName()); public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); new Thread(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); public void run() { gaston.bow(alphonse); }

23 Deadlock 2 Deadlock can happen if they both enter bow, then attempt to invoke bowback on each other. Both have a lock (from bow), and can’t obtain each others lock

24 Starvation Thread A obtains a lock another Thread B needs
Thread A never releases lock, or computes for very long amounts of time with lock Thread B cannot progress (or progresses very slowly)

25 Livelock Threads can act in response to each other (via InterruptedExceptions, for example) Think of two people trying to pass each other in a hall. Thread A moves left and Thread B moves right (they still block each other) Thread A moves right and Thread B moves left (they still block each other) Both are still active, but neither can progress

26 Guarded Blocks What if you want to wait for a field to be changed?
public void guardedJoy() { //Simple loop guard. Wastes processor time. Don't do this! while(!joy) {} System.out.println("Joy has been achieved!"); } What if you want to wait for a field to be changed?

27 Guarded Blocks 2 public synchronized guardedJoy() { //This guard only loops once for each special event, which may not //be the event we're waiting for. while(!joy) { try { wait(); } catch (InterruptedException e) {} } System.out.println("Joy and efficiency have been achieved!"); Be careful -- the InterruptedException might not be the one you were looking for -- put wait in a loop Why is guardedJoy synchronized? Can only call wait() when there is a lock (wait() releases the lock and suspends the thread)

28 Guarded Blocks 3 public synchronized notifyJoy() { joy = true; notifyAll(); } notifiyAll() notifies all threads waiting on a lock (and the scheduler decides which will get it next) notify() only notifies a single thread

29 Immutable Objects Immutable objects are objects that cannot change their state Very useful in concurrent programming -- since they cannot change state they cannot suffer from thread interference or have an inconsistent state

30 Immutable Objects 2 It’s easy to make an object immutable in Java
make all fields final (they can’t be modified) and private (they can’t be accessed) instantiate all fields within the constructor provide get methods for users to access copies of fields (primitives are naturally call-by- value)

31 High-Level Concurrency Objects
Lock objects Executors Concurrent collections Atomic variables

32 Lock Objects public boolean impendingBow(Friend bower) { Boolean myLock = false; Boolean yourLock = false; try { myLock = lock.tryLock(); yourLock = bower.lock.tryLock(); } finally { if (! (myLock && yourLock)) { if (myLock) { lock.unlock(); } if (yourLock) { bower.lock.unlock(); return myLock && yourLock; Lock objects support a wait/notify mechanism that can back out if the lock isn’t immediately available or a timeout expires This can be used to solve deadlocks

33 Executors Sometimes you want first class control over thread management and creation What if you’re running an application with 10,000+ concurrent objects? Most machines cannot allocate that many threads.

34 Executor Interfaces The java.util.concurrent package has:
Executor - base interface ExecutorService - subinterface of Executor which adds features that help manage tasks and their Executor ScheduledExecutorService - subinterface of ExecutorService supporting future and periodic execution of tasks

35 Executor Runnable r = ... //Run r in a thread (new Thread(r)).start(); //Use an executor to run r Executor e = ... e.execute(r); An executor is almost identical to a thread (except it uses execute) However, it may not necessarily use a new thread to run r (it may use an already existing one) -- more on that in ThreadPool

36 ExecutorService ExecutorServices also have a submit(...) method
submit can accept Callable objects and returns a Future value, which can be used to receive the result of the Callable object, and manage the status of Callable and Runnable objects

37 ExecutorService package com.journaldev.threads; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class MyCallable implements Callable<String> {      public String call() throws Exception {         Thread.sleep(1000);         //return the thread name executing this callable task         return Thread.currentThread().getName();     }           public static void main(String args[]){         //Get ExecutorService from Executors utility class, thread pool size is 10         ExecutorService executor = Executors.newFixedThreadPool(10);         //create a list to hold the Future object associated with Callable         List<Future<String>> list = new ArrayList<Future<String>>();         //Create MyCallable instance         Callable<String> callable = new MyCallable();         for(int i=0; i< 100; i++){             //submit Callable tasks to be executed by thread pool             Future<String> future = executor.submit(callable);             //add Future to the list, we can get return value using Future             list.add(future);         }         for(Future<String> fut : list){             try {                 //print the return value of Future, notice the output delay in console                 // because Future.get() waits for task to get completed                 System.out.println(new Date() + “::” + fut.get());             } catch (InterruptedException | ExecutionException e) {                 e.printStackTrace();             }         //shut down the executor service now         executor.shutdown(); }

38 ScheduledExecutorService
Adds a schedule method which executes a Runnable or Callable after a delay Can also specify scheduleAtFixedRate and scheduleWithFixedDelay to execute tasks repeatedly

39 Thread Pools Consist of a pool of worker threads to process tasks
This allows many concurrent objects to be controlled with a fixed or somewhat fixed number of threads

40 Thread Pools 2 java.util.concurrent.Executors has many static methods to create Executors (or thread pools): newFixedThreadPool - a thread pool with a fixed number of threads newCachedThreadPool - a thread pool that creates new threads when needed but also reuses threads that have been released by their tasks newSingleThreadPool - a thread pool that uses only one thread and ScheduledExecutorService versions of the same

41 Concurrent Collections
BlockingQueue -- A queue that blocks if you add to a full queue, and blocks if you try to remove from an empty queue ConcurrentMap -- A Map with atomic methods ConcurrentNavigableMap -- a concurrent map that supports partial matches

42 Atomic Variables Remember the counter class?
import java.util.concurrent.atomic.AtomicInteger; class AtomicCounter { private AtomicInteger c = new AtomicInteger(0); public void increment() { c.incrementAndGet(); } public void decrement() { c.decrementAndGet(); public int value() { return c.get(); Remember the counter class? This is faster and doesn’t require using synchronized Java has many atomic class implementations

43 Actors Threads, synchronization, etc can be extremely complex (leading to many headaches and sleepless nights) Just as Java made memory management significantly easier than c (and c++), actors make concurrency MUCH easier

44 Actors 2

45 Actors 3 Combine state and behavior (a thread of control)
Encapsulate state (all fields/methods are private) Only act in response to asynchronous messages (when you send a message it doesn’t block for a response) In response to a message an actor can send other messages, change its state and/or create new actors Process messages from its mailbox in first-in-first-out order No shared memory means no memory inconsistency No blocking methods/message sends means no deadlocks Only issue is you have to do all communication carefully via message passing (need to make sure you don’t send an object reference that two actors could modify concurrently)

46 Actors in Java public class MyActor {
private LinkedList<Message> mailbox = new LinkedList<Message>(); public synchronized void putMessage(Message message) { mailbox.addLast(message); notify(); } private synchronized Message getMessage() { if (mailbox.isEmpty()) { try { wait(); } catch (InterruptedException e) { ... } return mailbox.removeFirst(); private doSomething(Message message) { ... } //process messages here public void run() { while (true) { Message message = getMessage(); doSomething(message);

47 Actor Languages Erlang - Functional: SALSA - Java based: (implemented in Java) Scala - Pattern based: lang.org/ (implemented in Java)


Download ppt "Java Threads & Concurrency"

Similar presentations


Ads by Google