A running program is a collection of “threads” – essentially independent execution streams...

31
Note 5 Threads SE2811 Software Component Design Dr. Rob Hasker (based on slides by Dr. Mark Hornick)

Transcript of A running program is a collection of “threads” – essentially independent execution streams...

Page 1: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Note 5Threads

SE2811 Software Component DesignDr. Rob Hasker (based on slides by Dr. Mark Hornick)

Page 2: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

What SE1011 students are told…

• When the main() method is called, the instructions within the method begin to execute in sequence• The program terminates when the main() method finishes executing• But is this really true?

Page 3: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The ugly truth…

• A running program is a collection of “threads” – essentially independent execution streams•When the main() method is called, the instructions within the method begin to execute in sequence on a primary thread• The program terminates when the primary thread, and any additional threads, finish executing

Page 4: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

What’s a Thread?

Defining Process: A process is most easily understood as a program or application running on your PC

A process generally has a complete, private set of basic run-time resources, in particular:• Its own memory space• Execution priority• A list of threads that execute within it• A set of credentials with which to execute (usually

yours)• These provide authorization to access various resources

such as files

Page 5: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

By default, a Process creates and executes a single, primary Thread

BUT:A process can create and execute more than one thread

The JVM works with the OS to create processes and threads• The underlying OS provides the

essential multiprocessing support

Page 6: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Modern systems: multiple processes run simultaneously

• (On single-CPU PC’s) each process runs individually for a discrete time period

while one process runs, other processes sleep

• The process currently executing changes very rapidly - every few milliseconds

Operating systems use a scheduler to distribute CPU time among processes

• The net effect is that you (the user) observe all processes running simultaneously and continuously

Page 7: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Java application: the JVM creates a Process and a Primary Thread

• The primary thread begins executing the main() method in the main class

Note: other Java programs, like applets, begin execution with an init() method

• If no other threads are created, the process terminates when the primary thread terminates

That is, when there are no more instructions to execute on that thread

Page 8: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Threads wind their way through the code until they run out of instructions to execute

public class App {

public static void main(String[] args) {

App me = new App();

me.method_A();

}

private void method_A() {

// more code here

method_B();

return;

}

private void method_B() {

return;

}

private void method_C() {

// more code here

}

}

Single-threaded application

Page 9: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Where do other threads come from?

1. Additional threads are created by a Swing-based application

Java applications that create and display windows cause Swing to create additional threads

2. Additional threads are created by various Java utility classes

Eg: the Timer class

3. Threads can be created, controlled explicitly

Page 10: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Creating a multi-threaded application using Swing

1. Create a JFrame window containing JButtons, JTextField, etc.

2. Connect the JButtons, etc. to an ActionListener

3. Make the window visible• Once the window is visible, a second thread is

created• All calls to actionPerformed() occur on the

second thread• The Event-Dispatching Thread

Page 11: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Using a Timer is fairly straighforward:

import javax.swing.Timer;

Timer timer = new Timer(timeoutPeriod, eventHandler);

timer.start();

The eventHandler argument to the constructor is a reference to a class that implements Timer ActionListener• That is, eventHandler contains an actionPerformed()

method. This is similar to how Swing events are handled

• Whenever the Timer generates a timeout event, the JVM invokes actionPerformed() on another thread• JVM uses the Event Dispatch thread when available; otherwise a

“worker” thread is created

Page 12: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Explicitly creating additional threads

Thread t = new Thread(r);

t.start();

The r argument to the Thread constructor is a reference to a class that implements the Runnable interface• Runnable declares a single method: public

void run()

When the Thread’s start() method is called, the instructions in the run() method begin executing on the new thread.start() returns essentially immediately; it does not wait for the

started thread to finish execution

Page 13: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The main class may implement the Runnable interface itself:

public class App implements Runnable {

public static void main(String[] args) {

App me = new App();

me.method_A();

}

private void method_A() {

// more code here

method_B();

return;

}

private void method_B() {

Thread t = new Thread(this); // App is runnable!

t.start(); // start executing the run() method

return;

}

public void run() {

// more code here

}

}

Page 14: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

public class App implements Runnable{

public static void main(String[] args) {

App me = new App()

me.method_A();

}

private void method_A() {

// more code here

method_B();

return

}

private void method_B() {

Thread t = new Thread(this);

t.start();// execute run() on new thread

return;

}

public void run() {

// more code here

}

}

Both threads execute simultaneously and independently after the secondary thread is started

Page 15: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The secondary thread may execute a method defined in another class that implements Runnable

public class App {

public static void main(String[] args) {

App me = new App();

me.method_A();

}

private void method_A() {

ThreadRunner tr = new ThreadRunner();

Thread t = new Thread(tr);

t.start();

return;

}

private class ThreadRunner implements Runnable { // inner class

public void run() {

// more code here

}

}

}

Page 16: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The secondary thread may execute a lambda expression

public class App {

public static void main(String[] args) {

App me = new App();

me.method_A();

}

private void method_A() {

ThreadRunner tr = new ThreadRunner();

// assume declared x, y, z here...

Thread t = new Thread(()-> method_to_run(x, y, z));

t.start();

return;

}

private void method_to_run(int a, int b, String q) {

System.out.print(a + b);

System.out.print(q);

}

}

This method gets executed in place of the run (when

t.start() is executed)

Page 17: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

An application may be designed to execute the same instructions on more than one thread at the same time

public class App implements Runnable {public static void main(String[] args) {

App me = new App();me.method_A();

} private void method_A() {

ThreadRunner tr = new ThreadRunner();Thread t = new Thread(tr);t.start(); // execute run() on new secondary threadmethod_C(); // execute method_C on the primary

thread}private void method_C() {

// more code here } public void run() {

// some other instruction is here method_C(); // execute method_C on the secondary thread}

}

Page 18: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Question:

Is it a good idea to let two (or more) threads execute the same code at the same time?

See https://faculty-web.msoe.edu/hasker/se2811/samples/

Page 19: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Fortunately, Java supports several mechanisms for synchronizing the execution of multiple threads

S

Keeping code thread-safe

Page 20: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The Thread class’s join() method is one way of synchronizing two threads:

Thread t = new Thread(cref);

t.start();

t.join(); // wait for 2nd thread to finish…

method_C(); // …before executing next inst.

• The second Thread starts executing the instructions in the run() method.

• The current thread (the launcher of the second thread) waits until the second thread finishes

Page 21: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

If a method is declared to be synchronized, it will only be run on a single thread at a time

public class App implements Runnable {public static void main(String[] args) {

App me = new App()me.method_A();

} private void method_A() {

ThreadRunner tr = new ThreadRunner();Thread t = new Thread(tr);t.start();method_C(); // run method_C on the primary thread

}private synchronized void method_C() {

// More code here } public void run() {

// some other instructions here method_C(); // run method_C on the secondary thread}

}

Page 22: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Once a thread enters a synchronized method, no other threads can enter until the first thread completes execution of the method, and exits the method.

private synchronized void method_C() {

<statement 1>

<statement 2>

<statement 3>

}

Thread x Thread y Thread z

When Thread x leaves the method, the Scheduler arbitrarily allows one of the other threads to enter the method. When the second thread exits, the Scheduler allows another waiting thread to enter.

If all threads get to the method at the same time, the thread that gets to enter the method first is determined arbitrarily by the Scheduler.

Page 23: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Once a thread enters a synchronized method, no other threads can enter until the first thread completes execution of the method, and exits the method.

private synchronized void method_C() {

<statement 1>

<statement 2>

<statement 3>

}

Thread x Thread y Thread z

When Thread x leaves the method, the Scheduler arbitrarily allows one of the other threads to enter the method. When the second thread exits, the Scheduler allows another waiting thread to enter.

If all threads get to the method at the same time, the thread that gets to enter the method first is determined arbitrarily by the Scheduler.

Add syncronized to count_up()

Page 24: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Is synchronized the solution to everything?

Can you think of any disadvantage to making a method synchronized?

Page 25: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

If only a few statements within a method need to be guarded against simultaneous execution, use a synchronized block instead of making the entire method synchronized.

private void method_C() {

<safe statement 1>

<safe statement 2>

synchronized( <sync_object> ) {

<unsafe statement 3>

<unsafe statement 4>

<unsafe statement 5>}

<safe statement 6>

}

Thread x Thread y Thread z

When Thread x leaves the block, the Scheduler arbitrarily allows one of the other threads to enter.

Page 26: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

The synchronizing object can be any object

• Java’s Object class incorporates the concept of something called a monitor

•Monitors are used to guard the gates of synchronized blocks

•Monitors only become active within a synchronized block

Page 27: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Since every class derives from Object, the class containing a synchronized block can act as the Monitor for the block:

private void method_C() {

<safe statement 1>

<safe statement 2>

synchronized( this ) { // gate down

<unsafe statement 3>

<unsafe statement 4>

<unsafe statement 5>} // gate up

<safe statement 6>

}

Thread x Thread y Thread z

Page 28: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Or any generic Object can act as a Monitor

private Object guard = new Object();private void method_C() {

<safe statement 1>

<safe statement 2>

synchronized( guard ) { // gate down

<unsafe statement 3>

<unsafe statement 4>

<unsafe statement 5>} // gate up

<safe statement 6>

}

Thread x Thread y Thread z

Page 29: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Consider the following code. Suppose all threads reach the for() loop simultaneously.

How do the threads compete to run the for() loop?

private Object guard = new Object();private void method_C() {

<safe statement 1>

<safe statement 2>

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

synchronized( guard ) { // gate down

<unsafe statement 3>

<unsafe statement 4>

<unsafe statement 5> } // gate up

} // end for

<safe statement 6>

}

Thread x Thread y Thread z

Page 30: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

After each thread executes the synchronized section, it can notify the Monitor that another thread can be allowed to enter the synchronized block as soon as it relinquishes ownership of the synchronized section by entering a wait (or exiting the synchronized section)

private Object guard = new Object();private void method_C() {

<safe statement 1>

<safe statement 2>

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

synchronized( guard ) { // gate down

<unsafe statement 3>

<unsafe statement 4>

<unsafe statement 5>

guard.notify(); // signal waiting threads

guard.wait(); // wait for other threads }

} // end for

<safe statement 6>

}

Thread x Thread y Thread z

Page 31: A running program is a collection of “threads” – essentially independent execution streams When the main() method is called, the instructions within.

Review• Process: running application• memory, priority, permissions, threads

• Thread: execution stream• Essentially: a stream of instructions executed by CPU in a

process context

• Creating threads• Java Swing or JavaFx, Timer, new Thread()

• A thread of a problem• What happens if two threads access the same memory at

the same time• Using synchronized to avoid the problem