Types and type classes - University of Waikato

Download Report

Transcript Types and type classes - University of Waikato

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
• 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]