Transcript Week 6

Practical Session 6
•
•
•
•
•
•
Multitasking vs. multithreading
Threads
Concurrency vs. Parallelism
Java Threads
Thread confinement
Object/Class Immutability
Multitasking vs. Multithreading
• Multitasking:
– Running more than one process on same processor.
– Uses context switching between different processes:
(context=CPU state=content of CPU registers + program
counter)
• Switching from process A to B:
– Context of process A is stored.
– Context of process B is restored.
• Multithreading:
– Running more than one thread under same process.
– Has the ability of resource sharing – all threads can
access all resources of a process.
Threads
• Definition
– A way to share a single CPU between multiple tasks.
• Benefits
– Allows maintaining responsiveness of an application.
• HTTP Server waiting for requests
– Enable cancellation of separate tasks
– Some problems require parallelism
• Google’s Map/Reduce
– Allows monitoring status of a resource (data base)
– Allows taking advantage of multiple processors
Concurrency vs. Parallelism
• Concurrency:
– Two tasks can start and compete for CPU resources
• Two threads running on same processor
• They “share” the processor.
• Parallelism
– Two tasks that run at the same time in parallel.
• They do not compete on process time.
• Threads are executing simultaneously
Concurrency vs. Parallelism
CPU
Copyright © 2002, DeLorme
CPU1
CPU2
Java Threads
• Done by implementing the interface
java.lang.Runnable.
• java.lang.Runnable
– Allows any class that implements it to operate as a
thread.
– Requires one method to be implemented:
• public void run()
– Implementation:
class <className> implements Runnable {
public void run(){
//the “main” function of the thread
}
}
How to Run Threads
• By implementing Runnable and wrapping it with a Thread
instance.
– takes a single Runnable object and executes it in a separate thread.
– It is activated by calling start()
• calls the Runnable run() method.
• By implementing Runnable and passing it to an Executor.
• By extending the Thread class.
Wrapped by a Thread- Threads01.java
class SimpleRunnable implements Runnable {
private String name;
SimpleRunnable(String name) {
this.name = name;
}
//prints name three time waits 0.1 second between each print
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("RUNNABLE:" + this.name);
try {
Thread.sleep(100);//time in miliseconds
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class Threads01 {
//creates to simeRunnable threads and starts them
public static void main(String[] a) {
SimpleRunnable r1 = new SimpleRunnable("r1");
Thread t1 = new Thread(r1);
SimpleRunnable r2 = new SimpleRunnable("r2");
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
The order of start does not
guarantee the order of
execution.
Runnable Executor
• Used to run threads that implemented Runnable
• Decouples task creating and task running:
– Class does not have to be ran right after creation
• Creating the Executor:
• ExecutorService e = Executors.newFixedThreadPool(<numberOfThreads>);
– numberOfThreads: maximal number of threads running at same time.
• Executing the thread:
– e.execute(Runnable object);
• Shutting down executor:
– e.shutdown()
• Causes the executor not to accept any new threads, and close all threads when all submitted tasks are
done.
Using Executor - Threads01e.java
class SimpleRunnable implements Runnable {
private int m_number;
public SimpleRunnable(int i) {
this.m_number = i;
}
/**
* Main lifecycle of the task.
* Prints the task ID 10 times.
*/
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + m_number);
}
}
}
import java.util.concurrent.*;
public class Threads01e {
public static void main(String[] a) {
// Create an executor:
ExecutorService e = Executors.newFixedThreadPool(3);
// create 10 runnables, and execute them.
for(int i=0;i<10;i++) {
System.out.println("creating a new task: " + i + " ");
SimpleRunnable r = new SimpleRunnable(i);
e.execute(r);
}
e.shutdown();
}
}
Extending Java Threads
• Java.lang.Thread
– Allows maximal threading functionality
– Less common than Runnable, however much more powerful.
– Requires one method to be implemented:
• public void run()
• Implementation:
class <classname> extends Thread{
public void run(){
//thread “main” function
}
}
Threads can be Dangerous
• Having things run "at the same time, in the same place", can
be dangerous.
• The two tasks can interfere with each other, and unexpected
results might occur.
Example – shared counter
public class Counter{
private int fCounter;
public Counter(){
fCounter = 0;
}
public void increment(){
fCounter++;
}
public int getValue(){
return fCounter;
}
}
public class Incrementer implements Runnable {
Counter fCounter;
Incrementer(Counter ctr) {
fCounter = ctr;
}
/**
* Main lifecycle.
* increment the counter 200 times then dies.
*/
public void run() {
for (int i = 0; i<200; i++) {
fCounter.increment();
}
}
}
public class Threads03{
// Demonstrating problems with access to a shared resource.
public static void main(String[] a) {
for (int i=1;i<10;i++){
// create our shared object
Counter ctr = new Counter();
Thread t1 = new Thread(new Incrementer(ctr));
Thread t2 = new Thread(new Incrementer(ctr));
t1.start();
t2.start();
//wait until their job is done
while (t1.isAlive() || t2.isAlive()); //wait until all done.
//print out result of attempt i
System.out.println("Attempt " + i + ", total value: " +
ctr.getValue());
}
}
}
}
Shared Resources and Safety
• Safety problems arise when multiple threads access the same
resource.
• A shared resource is any object that is visible to several
threads:
– global (static) objects
– non-primitive method parameters
– class members.
– Basically non-primitive variables.
class Foo {
public static double NUMBER = 33.3;
}
class ClassA {
public long i;
public Vector v;
class TaskA implements Runnable {
//...
private ClassA a;
private List lst;
public long r;
public void run() {
this.r = 2;
Not safe - Accessing a public member variable.
public ClassA() { /* ... */ }
this.a.doSomething(9, lst); Not Safe - The private member
public void doSomething(long x, List lst) {
}
variable (lst) is exposed to class
A.
long localVar = 0;
}
Object o;
class Main {
Not safe - Accessing a public
o = this.v.elementAt(2); member variable.
public static void main(String[] args) {
localVar += 2; Local variable - Safe
// ....
this.i += 2; Not safe - Accessing a public member variable.
ClassA o1 = new ClassA();
Primitive- Safe
x
+= 2;
Thread t1 = new Thread(new TaskA(o1));
lst.elementAt(2); Not Safe - Accessing a possible shared object (lst).
t1.start();
Foo.NUMBER = 4;
// ....
Not Safe (static - never safe!)
localVar = Foo.NUMBER ; Not Safe (static - never safe!)
}
}
}
}
Some Solutions
• Thread-confined A thread-confined object is owned exclusively
by and confined to one thread, and can be modified only by
the thread that owns it.
• Shared read-only A shared read-only object can be accessed
concurrently by multiple threads, but cannot be modified by
any thread. Shared read-only objects are immutable.
Solution 1 - Thread Confinement
• Problem is solved by not accessing the shared resources! By
not having shared resources.
• Called thread confinement:
– threads access local resources only.
• This way, no need to worry about thread safety since no thread
can access any other thread’s variables.
Example
//ThreadConfined
public Car createCar() {
Engine e = new FuelEngine();
List<Door> doors = new
LinkedList<Door>();
doors.add(new FrontDoor());
doors.add(new FrontDoor());
doors.add(new BackDoor());
doors.add(new BackDoor());
Radio r = new AMFMRadio();
Car c = new Car(e, doors, r);
return c;
}
//NotThreadConfined
// e is not confined to this method - it is
visible from the outside
public Car createCar(Engine e) {
List<Door> doors = new
LinkedList<Door>();
doors.add(new FrontDoor());
doors.add(new FrontDoor());
doors.add(new BackDoor());
doors.add(new BackDoor());
Radio r = new AMFMRadio();
Car c = new Car(e, doors, r);
return c;
}
Solution 2 - Immutability
• An immutable object cannot be changed after construction.
• Solves thread safety problem by not allowing any variable
modifications at all.
Immutable Class - conditions
• All of its fields are final
• The class is declared final (cannot be subclassed)
• The this reference is not allowed to escape during construction.
(the object is not fully constructed!)
For more info: http://www.ibm.com/developerworks/java/library/j-jtp0618/
• Any fields that contain references to mutable objects, such as
arrays, collections, or mutable classes like Date:
–
–
–
–
Are private
Are never returned or otherwise exposed to callers
Are the only reference to the objects that they reference
Do not change the state of the referenced objects after construction
/**
* The constructed class is immutable even-though it consists of mutable objects.
* The class is immutable due to its design, not just by using the final keyword.
* class ThreeStooges is declared to be final, which means that it cannot have
subclasses. */
public final class ThreeStooges {
private final Set<String> stooges = new HashSet<String>();
public ThreeStooges() {
stooges.add("Moe");
stooges.add("Larry");
stooges.add("Curly");
}
public boolean isStooge(String name) {
return stooges.contains(name);
}
}
it won't change after
construction, meaning it
won't be assigned with
another reference, but still
the object stooges is
mutable: its internal values
may change