260 likes | 360 Views
Intro to Threads. CIS 4350 Rolf Lakaemper. Threads. Definitions first (Wikipedia):
E N D
Intro to Threads CIS 4350 Rolf Lakaemper
Threads Definitions first (Wikipedia): “In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by an operating system scheduler… Multiple threads can exist within the same process and share resources such as memory”
Example Let’s start with a simple example. We want to write a program, that prints out a text every second.
Bad Implementation public static void main(String[] args) { long time = System.currentTimeMillis(); int counter = 0; while (true) { long currentTime = System.currentTimeMillis(); if (currentTime - time > 1000) { time = currentTime; System.out.println("Hello “+ counter)); counter++; } } }
Better yet Limited Implementation public static void main(String[] args) throws InterruptedException { long time = System.currentTimeMillis(); int counter = 0; while (true) { Thread.sleep(1000); System.out.println("Hello " + counter); counter++; } } This is a pause command. It indirectly points us to Threads, but let’s not care right now.
Example The limitation is, that the program • (a) pauses for 1 second • (b) requires a loop to be performed! Let’s extend the task, so these limitations become clear: We want the user to be able to end the program, by clicking ok in a dialog box. Unfortunately, when creating a dialog box, it waits for input (if we choose JOptionPane.showMessageDialog)).
Example • This does not work! Wait a second Print Time It’s stuck right here! Get input End
Example • What we need is a user input that does not wait. JAVA of course provides these, but, for this example, let’s build our own version. • Our non-waiting box will explain why Threads are needed: our example problem is trying to handle two tasks: printing the time and waiting for input. • This problem can be modeled in a more elegant way than in a single loop:
A better solution to our problem • We have one process (our program), with two sub-processes (THREADS), that run independently, yet communicate via a field (break flag) Process Thread 1 Thread 2 Wait a second Print Time Get User Input Check break-flag Set break flag Break flag End
Back to the Definition “…a thread of execution is the smallest sequence of programmed instructions that can be managed independently by an operating system scheduler… Multiple threads can exist within the same process and share resources such as memory” Our two threads! The time-print-thread, and the input-thread. Our process: one program. The shared resource: the break flag.
How to Code Threads in JAVA • When you start your usual JAVA program, it runs in a single thread, which starts the method main(). • Additional Threads can be started by instantiating classes of Type “Runnable”, i.e. classes that implement the “Runnable” interface. • “Runnable” declares the method “run()” • There’s a default implementation, the “Thread” class, we can extend our own classes from.
The example revisited Process Thread 1 Thread 2 Break flag
Main Process public class Main { private booleanbreakFlag; class TimePrint extends Thread { } class UserInput extends Thread { } // ---------------------------- Main() { breakFlag = false; new TimePrint().start(); new UserInput().start(); } public static void main(String[] args) throws InterruptedException { new Main(); } }
Remark: We are starting 3 threads here! • “main” • Thread1 • Thread2 “main” just dies after creating the other two. Thread1 dies when the break-condition is true Thread2 dies when ok was clicked. The process terminates when allthreads are dead, NOT when main terminates!
Thread 1 class TimePrint extends Thread { public void run(){ int counter = 0; while (!breakFlag){ try { Thread.sleep(1000); } catch (InterruptedException ex) { } System.out.println("Hello "+counter); counter++; } } } Shared resource!
Thread 2 class UserInput extends Thread { public void run(){ JOptionPane.showMessageDialog(null, "Stop the Program"); breakFlag = true; } } Shared resource!
Version 2: Implementation of the Runnable interface (example: Thread 2) class UserInput implements Runnable { public void run(){ JOptionPane.showMessageDialog(null, "Stop the Program"); breakFlag = true; } } … this version needs to be started using: new Thread(new UserInput()).start();
Advanced Threads can have multiple “states” We might talk about that later. …but we don’t necessarily have to.
Problems with Threads: Concurrency • We share resources! • If one thread writes to a resource while another one reads from it, we might be in trouble! • (the problem is that we only MIGHT be in trouble. One time we are, another we are not, which makes debugging ugly!) • The trouble: if the resources consist of multiple parts (e.g. an array, consisting of many members). If thread1 re-writes a part while thread2 reads another part, thread2 might have different partial versions of the resource read after completion. Even worse: if thread1 deletes the resource, while thread2 reads it, the program might crash! • If resources consist of only a single part, everything is fine.
Concurrency time Thread1 Starts to read Thread2 writes Thread1 Continues to read Thread1 Reading result: Array Array Array Array
“Single Part” resources are ok time Thread1 Starts and finishes reading Thread2 writes Thread1 Reading result:
Solution: make multi-part resources “Thread safe” - locking • A resource is thread safe when its access is “atomic”, i.e. a single virtual access cycle is needed. • This can be achieved by “locks”, which regulate access order. • Example:
Concurrency: Locking Example Version 1: no locking. Concurrency problem Method1 Access to Array Method2 Access to Array Trouble!!! Array
Concurrency: Locking Example Version 1: locking. No concurrency problem Method1 Access to Array Method2 Access to Array Lock Access Unlock Array
Locks • A lock is an atomic resource • It has two methods, which are virtual one cycle methods: lock() and unlock() • If a locked resource is attempted to be locked again, it blocks the access (makes the Thread wait) until it gets unlocked. • “Locking” a data structure is to surround the multi-cycle access to it with a lock.
Java Example • (example, see course website: “ThreadExamples”)