Slajd 1 - PowerPoint PPT Presentation

About This Presentation
Title:

Slajd 1

Description:

Programowanie obiektowe w j zyku Java Threads Bartosz Sakowicz Threads notifyAll, notify and wait The notifyAll method wakes up all threads waiting on the object in ... – PowerPoint PPT presentation

Number of Views:54
Avg rating:3.0/5.0
Slides: 44
Provided by: sak133
Category:

less

Transcript and Presenter's Notes

Title: Slajd 1


1
Programowanie obiektowe w jezyku Java Threads
Bartosz Sakowicz
2
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.
3
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.

4
Using the Timer and TimerTask
import java.util. public class Reminder
Timer timer public Reminder(int seconds)
timer new Timer() timer.schedule(new
RemindTask(), seconds1000) 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.")
5
Scheduling task for execution at particular hour
... //Date corresponding to 100100 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) ...
6
Stoping 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
    tasks run method.
  • Make the timers 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 timers scheduled tasks have
    finished executing, remove all references to the
    Timer object. Eventually, the timers thread will
    terminate.
  • Invoke the System.exit method, which makes the
    entire program (and all its threads) exit.

7
Programming 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.

8
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.
9
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.
10
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)
11
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() ...
12
Subclassing Thread
public class SimpleThread extends Thread
public SimpleThread(String str) super(str)
public void run() for (int i 0 i lt 10
i) System.out.println(i " "
getName()) try sleep((long)(Math.rando
m() 1000)) catch (InterruptedException
e) //thrown when other thread //
interrupt when one sleeping
System.out.println("DONE! " getName())
13
Implementing 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.
14
Creating threads
public class TwoThreadsDemo public static
void main (String args) new
SimpleThread("One").start() new
SimpleThread("Two").start()
15
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.sta
rt()
16
The Thread Life Cycle
17
Making 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.

18
Stopping 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 lt 100) i
System.out.println("i " i)
A thread with this run method dies naturally when
the loop completes and the run method exits.
19
Interrupts
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.
20
Supporting interruption
  • Situation when thread often invokes methods which
    throw InterruptedException
  • for (int i 0 i lt 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(importantInfoi) //Print a
    message

21
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 lt inputs.length
i) heavyCrunch(inputsi) if
(Thread.interrupted()) //We've been
interrupted no more crunching. return
OR in more complex applications if
(Thread.interrupted()) throw new
InterruptedException()
22
The 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.

23
Joins
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.
24
Thread 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.

25
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.

26
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 lt 10
i) cubbyhole.put(i) System.out.println(
"Producer " this.number " put " i)
try sleep((int)(Math.random()
100)) catch (InterruptedException e)

27
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 lt 10 i) value cubbyhole.get()
System.out.println("Consumer " this.number
" got " value)
28
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
29
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()
30
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.

31
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.
32
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
33
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
34
notifyAll, 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.
35
Atomic 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.

36
Deadlock
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?
37
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.
38
Starviation 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. Livelock A 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
39
Grouping 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.
40
The 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

41
Creating 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()
42
The 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.
43
High 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.
Write a Comment
User Comments (0)
About PowerShow.com