43
„Threads

„ Threads ”

Embed Size (px)

DESCRIPTION

„ Threads ”. Threads - basics. A thread is a single sequential flow of control within a program . A thread itself is not a program; it cannot run on its own. Rather, it runs within a program. Threads – basics(2). Some texts use the name lightweight process instead of thread. - PowerPoint PPT Presentation

Citation preview

Page 1: „ Threads ”

„Threads” „Threads”

Page 2: „ Threads ”

Threads

Threads - basicsThreads - basics

A thread is a single sequential flow of control within a

program. A thread itself is not a program; it cannot run on its

own. Rather, it runs within a program.

Page 3: „ Threads ”

Threads

Threads – basics(2)Threads – basics(2)

• Some texts use the name lightweight process instead of thread.

• A thread is similar to a real process in that a thread and a running program are both a single sequential flow of control.

• A thread is considered lightweight because it runs within the context of a full-blown program and takes advantage of the resources allocated for that program and the program's environment.

• As a sequential flow of control, a thread must carve out some of its own resources within a running program. (It must have its own execution stack and program counter for example) The code running within the thread works only within that context. Thus, some other texts use execution context as a synonym for thread.

Page 4: „ Threads ”

Threads

Using the Timer and TimerTask Using the Timer and TimerTask

import java.util.*;

public class Reminder {

Timer timer;

public Reminder(int seconds) {

timer = new Timer();

timer.schedule(new RemindTask(), seconds*1000); }

class RemindTask extends TimerTask {

public void run() {

System.out.println("Time's up!");

timer.cancel(); //Terminate the timer thread } }

public static void main(String args[]) {

new Reminder(5); System.out.println("Task scheduled."); } }

Page 5: „ Threads ”

Threads

Scheduling task for execution at particular hour Scheduling task for execution at particular hour

...

//Date corresponding to 10:01:00 pm today.

Calendar calendar = Calendar.getInstance();

calendar.set(Calendar.HOUR_OF_DAY, 22);

calendar.set(Calendar.MINUTE, 1);

calendar.set(Calendar.SECOND, 0);

Date time = calendar.getTime();

timer = new Timer();

timer.schedule(new RemindTask(), time);

...

Page 6: „ Threads ”

Threads

Stoping Timer ThreadsStoping Timer Threads

By default, a program keeps running as long as its timer threads are running. You can terminate a timer thread in four ways:

• Invoke cancel on the timer. You can do this from anywhere in the program, such as from a timer task’s run method.

• Make the timer’s thread a “daemon” by creating the timer like this: new Timer(true). If the only threads left in the program are daemon threads, the program exits.

• After all the timer’s scheduled tasks have finished executing, remove all references to the Timer object. Eventually, the timer’s thread will terminate.

• Invoke the System.exit method, which makes the entire program (and all its threads) exit.

Page 7: „ Threads ”

Threads

Programming threadsProgramming threads

There are two techniques for providing a run method for a thread:

• Subclassing Thread and Overriding run

• Implementing the Runnable Interface

java.lang.Thread represents a thread of control. It offers methods that allow you to set the priority of the thread, to assign a thread to a thread group and to control the running state of the thread (e.g., whether it is running or suspended).

The java.lang.Runnable interface represents the body of a thread. Classes that implement the Runnable interface provide their own run() methods that determine what their thread actually does while running. If a Thread is constructed with a Runnable object as its body, the run() method on the Runnable will be called when the thread is started.

Page 8: „ Threads ”

Threads

Programming threads(2)Programming threads(2)

There are two ways to define a thread:

One is to subclass Thread, override the run() method, and then instantiate your Thread subclass.

The second is to define a class that implements the Runnable method (i.e., define a run() method) and then pass an instance of this Runnable object to the Thread() constructor.

In either case, the result is a Thread object, where the run() method is the body of the thread.

Page 9: „ Threads ”

Threads

Programming threads(3)Programming threads(3)

When you call the start() method of the Thread object, the interpreter creates a new thread to execute the run() method.

This new thread continues to run until the run() method exits, at which point it ceases to exist. Meanwhile, the original thread continues running itself, starting with the statement following the start() method.

Page 10: „ Threads ”

Threads

Programming threads(4)Programming threads(4)

final List list; // Some unsorted list ; initialized elsewhere

/** A Thread class for sorting a List in the background */

class BackgroundSorter extends Thread {

List l;

public BackgroundSorter(List l) { this.l = l; }

public void run() { Collections.sort(l); }

}

Page 11: „ Threads ”

Threads

Programming threads(5)Programming threads(5)...

Thread sorter = new BackgroundSorter(list); // Start it running;

/** the new thread runs the run() method above, while the original thread continues with whatever statement comes next:*/

sorter.start();

// Here's another way to define a similar thread

Thread t = new Thread(new Runnable() { public void run() { Collections.sort(list); } });

t.start();

...

Page 12: „ Threads ”

Threads

Subclassing ThreadSubclassing Thread

public class SimpleThread extends Thread {

public SimpleThread(String str) { super(str); }

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println(i + " " + getName());

try {

sleep((long)(Math.random() * 1000));

} catch (InterruptedException e) {} //thrown when other thread

// interrupt when one sleeping

} System.out.println("DONE! " + getName());

}

}

Page 13: „ Threads ”

Threads

Implementing RunnableImplementing Runnable

The difference between the two classes is that a Thread is supposed to represent how a thread of control runs (its priority level, the name for the thread), and a Runnable defines what a thread runs. In both cases, defining a subclass usually involves implementing the run() method to do whatever work you want done in the separate thread of control.

If your class must subclass some other class (the most common example being Applet), you should use Runnable.

Page 14: „ Threads ”

Threads

Creating threadsCreating threads

public class TwoThreadsDemo {

public static void main (String[] args) {

new SimpleThread("One").start();

new SimpleThread("Two").start();

}

}

Page 15: „ Threads ”

Threads

The Thread Life CycleThe Thread Life Cycle

Page 16: „ Threads ”

Threads

The Thread Life Cycle(2)The Thread Life Cycle(2)

public class Clock extends Applet implements Runnable {

private Thread clockThread = null;

public void start() {

if (clockThread == null) { //we check if the user

//already have seen an applet

// create a Thread

clockThread = new Thread(this, "Clock");

// start a Thread

clockThread.start();

}

}

Page 17: „ Threads ”

Threads

Making a Thread not runnableMaking a Thread not runnable

A thread becomes not runnable when one of these events occurs:

• Its sleep method is invoked.

• The thread calls the wait method to wait for a specific condition to be satisifed.

• The thread is blocking on I/O.

The escape route for every entrance into the not runnable state:

• If a thread has been put to sleep, then the specified number of milliseconds must elapse.

• If a thread is waiting for a condition, then another object must notify the waiting thread of a change in condition by calling notify or notifyAll.

• If a thread is blocked on I/O, then the I/O must complete.

Page 18: „ Threads ”

Threads

Stopping a ThreadStopping a Thread

A thread arranges for its own death by having a run method that terminates naturally. For example, the while loop in this run method is a finite loop - it will iterate 100 times and then exit:

public void run() {

int i = 0;

while (i < 100) {

i++;

System.out.println("i = " + i);

}

}

A thread with this run method dies naturally when the loop completes and the run method exits.

Page 19: „ Threads ”

Threads

InterruptsInterrupts

An interrupt is an indication to a thread that it should stop what it is doing and do something else.

A thread sends an interrupt by invoking interrupt on the Thread object for the thread to be interrupted.

Page 20: „ Threads ”

Threads

Supporting interruptionSupporting interruption

1) Situation when thread often invokes methods which throw InterruptedException:

for (int i = 0; i < importantInfo.length; i++) {

try {

Thread.sleep(4000); //Pause for 4 seconds

} catch (InterruptedException e) {

return; //We've been interrupted: no more messages.

}

System.out.println(importantInfo[i]); //Print a message

}

Page 21: „ Threads ”

Threads

Supporting interruption (2)Supporting interruption (2)

2) If a thread goes a long time without invoking a method that throws InterruptedException, it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received:

for (int i = 0; i < inputs.length; i++) { heavyCrunch(inputs[i]); if (Thread.interrupted()) {

//We've been interrupted: no more crunching. return;

} }

OR in more complex applications:

if (Thread.interrupted()) { throw new InterruptedException();

}

Page 22: „ Threads ”

Threads

The interrupt status flagThe interrupt status flag

• The interrupt mechanism is implemented using an internal flag known as the interrupt status.

• Invoking Thread.interrupt sets this flag.

• When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared.

• The non-static Thread.isInterrupted, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

• By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.

Page 23: „ Threads ”

Threads

JoinsJoins

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing:

t.join();

causes the current thread to pause execution until t's thread terminates.

Overloads of join allow the programmer to specify a waiting period.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

Page 24: „ Threads ”

Threads

Thread priorityThread priority

• When a Java thread is created, it inherits its priority from the thread that created it.

• You can also modify a thread's priority at any time after its creation using the setPriority method.

• Thread priorities are integers ranging between MIN_PRIORITY and MAX_PRIORITY (constants defined in the Thread class).

• The higher the integer, the higher the priority.

• At any given time, when multiple threads are ready to be executed, the runtime system chooses the runnable thread with the highest priority for execution.

• At any given time, the highest priority thread is running, but this is not guaranteed. For this reason, use priority only to affect scheduling policy for efficiency purposes. Do not rely on thread priority for algorithm correctness.

Page 25: „ Threads ”

Threads

The consumer/producer example (synchronization)The consumer/producer example (synchronization)

• The Producer generates an integer between 0 and 9 and stores it in a CubbyHole object, and prints the generated number.

• The Consumer consumes all integers from the CubbyHole (the exact same object into which the Producer put the integers) as quickly as they become available.

Page 26: „ Threads ”

Threads

The consumer/producer ...(2)The consumer/producer ...(2)

public class Producer extends Thread {

private CubbyHole cubbyhole;

private int number;

public Producer(CubbyHole c, int number) {

cubbyhole = c; this.number = number; }

public void run() {

for (int i = 0; i < 10; i++) {

cubbyhole.put(i);

System.out.println("Producer #" + this.number + " put: " + i);

try {

sleep((int)(Math.random() * 100));

} catch (InterruptedException e) { } } } }

Page 27: „ Threads ”

Threads

The consumer/producer ...(3)The consumer/producer ...(3)

public class Consumer extends Thread {

private CubbyHole cubbyhole;

private int number;

public Consumer(CubbyHole c, int number) {

cubbyhole = c;

this.number = number; }

public void run() {

int value = 0;

for (int i = 0; i < 10; i++) {

value = cubbyhole.get();

System.out.println("Consumer #" + this.number + " got: " + value); } } }

Page 28: „ Threads ”

Threads

The consumer/producer ...(4)The consumer/producer ...(4)

One problem arises when the Producer is quicker than the Consumer (e.g. higher priority) and generates two numbers before the Consumer has a chance to consume the first one. Part of the output might look like this:

Consumer #1 got: 3

Producer #1 put: 4

Producer #1 put: 5

Consumer #1 got: 5

Or Consumer is quicker then Producer:

Producer #1 put: 4

Consumer #1 got: 4

Consumer #1 got: 4

Producer #1 put: 5

Page 29: „ Threads ”

Threads

The consumer/producer ...(5)The consumer/producer ...(5)

The main program:

public class ProducerConsumerTest {

public static void main(String[] args) {

CubbyHole c = new CubbyHole();

Producer p1 = new Producer(c, 1);

Consumer c1 = new Consumer(c, 1);

p1.start();

c1.start();

}

}

Page 30: „ Threads ”

Threads

The consumer/producer ...(6)The consumer/producer ...(6)

Problems such as described are called race conditions.

The activities of the Producer and Consumer must be synchronized in two ways:

• The two threads must not simultaneously access the CubbyHole. A Java thread can prevent this from happening by locking an object. When an object is locked by one thread and another thread tries to call a synchronized method on the same object, the second thread will block until the object is unlocked.

• The two threads must do some simple coordination. That is, the Producer must have some way to indicate to the Consumer that the value is ready and the Consumer must have some way to indicate that the value has been retrieved.

Page 31: „ Threads ”

Threads

The consumer/producer ...(7)The consumer/producer ...(7)

Will it work?

public class CubbyHole {

private int contents;

private boolean available = false;

public synchronized int get() {

if (available == true) { available = false; return contents; }

}

public synchronized void put(int value) {

if (available == false) { available = true; contents = value; }

}

}

Answer: No, it will not.

Page 32: „ Threads ”

Threads

The consumer/producer ...(8)The consumer/producer ...(8)

The correct implementation of get method:

public synchronized int get() {

while (available == false) {

try {

wait(); // wait for Producer to put value

} catch (InterruptedException e) { }

}

available = false;

notifyAll(); // notify Producer that value has been retrieved

return contents;

}

Page 33: „ Threads ”

Threads

The consumer/producer ...(9)The consumer/producer ...(9)

The correct implementation of put method:

public synchronized void put(int value) {

while (available == true) {

try {

wait(); // wait for Consumer to get value

} catch (InterruptedException e) { }

}

contents = value;

available = true;

notifyAll(); // notify Consumer that value has been set

}

Page 34: „ Threads ”

Threads

notifyAll, notify and waitnotifyAll, notify and wait

The notifyAll method wakes up all threads waiting on the object in question (in this case, the CubbyHole). The awakened threads compete for the lock. One thread gets it, and the others go back to waiting. The Object class also defines the notify method, which arbitrarily wakes up one of the threads waiting on this object (but you cannot choose which).

There are two other versions of the wait method:

wait(long timeout)

Waits for notification or until the timeout period has elapsed. timeout is measured in milliseconds.

wait(long timeout, int nanos)

Waits for notification or until timeout milliseconds plus nanos nanoseconds have elapsed.

Page 35: „ Threads ”

Threads

Atomic accessAtomic access

In programming, an atomic action is one that effectively happens all at once.

Increment expression, such as c++, does not describe an atomic action.

Actions that are atomic: • Reads and writes are atomic for reference variables and for most primitive

variables (all types except long and double). • Reads and writes are atomic for all variables declared volatile (including

long and double variables).

Changes to a volatile variable are always visible to other threads.

Using simple atomic variable access is more efficient than accessing these variables through synchronized code.

Page 36: „ Threads ”

Threads

DeadlockDeadlock

The philosophers problem:

Five philosophers are sitting at a round table. In front of each philosopher is a bowl of rice. Between each pair of philosophers is one chopstick. Before an individual philosopher can take a bite of rice he must have two chopsticks--one taken from the left, and one taken from the right. The philosophers must find some way to share chopsticks such that they all get to eat.

What is a solution, when all starts immediately?

Page 37: „ Threads ”

Threads

Deadlock (2)Deadlock (2)

We can change the rules by numbering the chopsticks 1 through 5 and insisting that the philosophers pick up the chopstick with the lower number first. The philosopher who is sitting between chopsticks 1 and 2 and the philosopher who is sitting between chopsticks 1 and 5 must now reach for the same chopstick first (chopstick 1) rather than picking up the one on the right. Whoever gets chopstick 1 first is now free to take another one. Whoever doesn't get chopstick 1 must now wait for the first philosopher to release it. Deadlock is not possible.

The best choice is to prevent deadlock rather than to try and detect it. Deadlock detection is very complicated . The same with starvation.

Page 38: „ Threads ”

Threads

Starviation and LivelockStarviation and Livelock

Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress.

This happens when shared resources are made unavailable for long periods by "greedy" threads.

For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.

LivelockA thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work

Page 39: „ Threads ”

Threads

Grouping ThreadsGrouping Threads

Every Java thread is a member of a thread group. Thread groups provide a mechanism for collecting multiple threads into a single object and manipulating those threads all at once, rather than individually. For example, you can start or suspend all the threads within a group with a single method call. Java thread groups are implemented by the ThreadGroup class in the java.lang package.

The runtime system puts a thread into a thread group during thread construction. When you create a thread, you can either allow the runtime system to put the new thread in some reasonable default group or you can explicitly set the new thread's group. The thread is a permanent member of whatever thread group it joins upon its creation - you cannot move a thread to a new group after the thread has been created.

Page 40: „ Threads ”

Threads

The default Thread GroupThe default Thread Group

• If you create a new Thread without specifying its group in the constructor, the runtime system automatically places the new thread in the same group as the thread that created it.

• When a Java application first starts up, the Java runtime system creates a ThreadGroup named main. Unless specified otherwise, all new threads that you create become members of the main thread group.

• If you create a thread within an applet, the new thread's group may be something other than main, depending on the browser or viewer that the applet is running in

Page 41: „ Threads ”

Threads

Creating Thread in a GroupCreating Thread in a Group

ThreadGroup myTG =

new ThreadGroup( "My Group of Threads");

Thread myThread =

new Thread(myTG, "a thread for my group");

To find out what group a thread is in, you can call its getThreadGroup method:

theGroup = myThread.getThreadGroup();

Page 42: „ Threads ”

Threads

The ThreadGroup classThe ThreadGroup class

ThreadGroups can contain not only threads but also other ThreadGroups. The top-most thread group in a Java application is the thread group named main. You can create threads and thread groups in the main group. You can also create threads and thread groups in subgroups of main.

Page 43: „ Threads ”

Threads

High level concurrency APIHigh level concurrency API

Lock objects support locking idioms that simplify many concurrent applications.

Executors define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.

Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.

Atomic variables have features that minimize synchronization and help avoid memory consistency errors.