120 likes | 180 Views
Threads “the future is parallel”. Multi-threading. Multi-tasking: do multiple things in parallel: Edit your game Surf the web Listen to mp3s … Also inside single App: mp3 player (decompress, play, graphics) but usually only 1 or 2 CPUs with 1 or 2 cores that switches between tasks
E N D
Multi-threading • Multi-tasking: do multiple things in parallel: • Edit your game • Surf the web • Listen to mp3s • … • Also inside single App: mp3 player (decompress, play, graphics) but usually only 1 or 2 CPUs with 1 or 2 cores that switches between tasks • Multi-threading similar, but inside a single program/process/context share data directly, same classes/methods/variables
Creating threads: 2 ways • Subclassing Class Thread class ExpensiveComputation extends Thread • Must implement run() method • Use start() on a new instance: • (new ExpensiveComputation()).start(); • Implement interface Runnable: class ExpensiveComputation implements Runnable • Must implement run() method • Start by wrapping inside a Thread instance: • Thread thread = new Thread(new ExpensiveComputation ()); • thread.start(); • Both will stop automatically, once run() finishes
Scheduling • Can be pre-emptive or cooperative, Each Thread should regularly call one of yield() wait() sleep() to give other threads a chance to run as well • All event handlers (all listeners) and repaint() execute in the same event-handling thread: methods like “actionPerformed()” should be fast, for more substantial computations they should: • Start a new thread • Somehow tell another thread what to do Otherwise screen repainting will suffer!
Synchronisation • If two (or more) threads access some value simultanously, and at least one want’s to modify the value, things can go wrong: a += 10; Thread1: (a1) read a, (b1) compute a+10, (c1) write a Thread2: (a2) read a, (b2) compute a+10, (c2) write a What is the value of a after the following sequence: a1,b1,a2,b2,c2,c1
Synchronized methods public synchronized void increment() { a += 10; } • Only one thread at a time can execute this method on the same instance no interleaving possible (“atomic action”) no inconsistencies • but: beware of inefficiencies/deadlocks
Higher level: java.util.concurrent • Lots of useful high-level stuff for concurrency: • E.g.Thread pools: • Threads use quite some resources (especially memory) • Pools limit the number of threads, queue requests for more threads/computation • Degrade more gracefully under high load
Thread pools • java.util.concurrent.Executors. newFixedThreadPool(int poolSize) creates an ExecutorService of n threads • Good default: poolSize = number of cores • submit(Runnable task) returns a Future • Must explicitly shutdown() ExecutorService
Runnable / Callable / Future • Future is a “Wrapper” representing the future value of the thread’s computation • Access with get(), will block until thread is finished => easy synchronisation • Runnable’s run() method returns only void • Callable’s call() method can return any Object, but does not take arguments => use constructor to “pass in” arguments
Code example int poolSize = 4; ExecutorService pool = Executors.newFixedThreadPool(poolSize); List<Future<Double>> future = new ArrayList<Future<Double>>(); for (int i = 0; i < max; i++) { future.add(pool.submit(new SomeComputation(i))); } // wait until all are finished and collect results: double total = 0.0; for (Future<Double> f: future) total += future.get(); pool.shutdown();
Cont. public class SomeComputation implements Callable<Double> { private int offset = -1; public SomeComputation(int offset) { this.offset = offset; } public Double call() { // some computation using “offset” // safe “atomic” output synchronized (System.out) { System.out.println(”someComputation offset = “ + offset + “ “ + someMessage); } return someResult; } }
java.util.concurrent.atomic • Thread-safe “atomic” access for certain objects and references • E.g. AtomicInteger int addAndGet(delta) Atomically adds the given value to the current value and returns result. [see also concurrent versions of collections] [synchronization can be expensive, can lead to deadlocks and similar, avoid, or replace with high-level constructs]