COMP 213. Advanced Object-oriented Programming. Lecture 23. Shared Variables and Synchronization

Similar documents
MultiThreading 07/01/2013. Session objectives. Introduction. Introduction. Advanced Java Programming Course

Advanced Java Programming Course. MultiThreading. By Võ Văn Hải Faculty of Information Technologies Industrial University of Ho Chi Minh City

SUMMARY FUTURES CALLABLES CONCURRENT PROGRAMMING THREAD S ADVANCED CONCEPTS

Lecture 03: Thread API (continue)

Multithreaded Programming Part II. CSE 219 Stony Brook University, Department of Computer Science

Animation Part 2: MoveableShape interface & Multithreading

Problems with Concurrency. February 19, 2014

INF 212 ANALYSIS OF PROG. LANGS CONCURRENCY. Instructors: Crista Lopes Copyright Instructors.

Chair of Software Engineering. Java and C# in depth. Carlo A. Furia, Marco Piccioni, Bertrand Meyer. Java: concurrency

CS 351 Design of Large Programs Threads and Concurrency

System Programming. Practical Session 4: Threads and Concurrency / Safety

Common Java Concurrency pitfalls. Presented by : Kunal Sinha Austin Java Users Group 03/26/2019

Le L c e t c ur u e e 7 To T p o i p c i s c t o o b e b e co c v o e v r e ed e Multithreading

Computation Abstractions. Processes vs. Threads. So, What Is a Thread? CMSC 433 Programming Language Technologies and Paradigms Spring 2007

Note: Each loop has 5 iterations in the ThreeLoopTest program.

Multi-threading in Java. Jeff HUANG

JAVA and J2EE UNIT - 4 Multithreaded Programming And Event Handling

Advanced Object-oriented Programming

Parallel Programming Practice

CST242 Concurrency Page 1

Parallel Programming Practice

Only one thread can own a specific monitor

Learning from Bad Examples. CSCI 5828: Foundations of Software Engineering Lecture 25 11/18/2014

CS 159: Parallel Processing

G Programming Languages Spring 2010 Lecture 13. Robert Grimm, New York University

CMSC 132: Object-Oriented Programming II. Threads in Java

CS 556 Distributed Systems

Thread Safety. Review. Today o Confinement o Threadsafe datatypes Required reading. Concurrency Wrapper Collections

Principles of Software Construction: Concurrency, Part 2

Threads and Parallelism in Java

CmpSci 187: Programming with Data Structures Spring 2015

Java Threads. COMP 585 Noteset #2 1

Concurrency in Object Oriented Programs 4. Object-Oriented Software Development COMP4001 CSE UNSW Sydney Lecturer: John Potter

Concurrency Utilities: JSR-166

UNIT V CONCURRENT PROGRAMMING

G51PGP Programming Paradigms. Lecture 009 Concurrency, exceptions

Threads Chate Patanothai

-Aditya Bhave CSCI-5448 Graduate Presentation

Multiple Inheritance. Computer object can be viewed as

Lecture 9: Introduction to Monitors

Multithreaded Programming

Concurrency CSCI 201 Principles of Software Development

CSCD 330 Network Programming

CPS221 Lecture: Threads

Java s Implementation of Concurrency, and how to use it in our applications.

04-Java Multithreading

COURSE 11 PROGRAMMING III OOP. JAVA LANGUAGE

Threads and Locks, Part 2. CSCI 5828: Foundations of Software Engineering Lecture 08 09/18/2014

Unit 4. Thread class & Runnable Interface. Inter Thread Communication

Module - 4 Multi-Threaded Programming

Multitasking Multitasking allows several activities to occur concurrently on the computer. A distinction is usually made between: Process-based multit

Advanced Programming Concurrency

Shared Objects & Mutual Exclusion

Advanced Programming Methods. Lecture 6 - Concurrency in Java (1)

COMP 346 WINTER Tutorial 2 SHARED DATA MANIPULATION AND SYNCHRONIZATION

Synchronization synchronization.

Problems with Concurrency

The Java ExecutorService (Part 1)

Multithreading Pearson Education, Inc. All rights reserved.

[module lab 1.2] STRUCTURING PROGRAMS IN TASKS

Concurrency & Parallelism. Threads, Concurrency, and Parallelism. Multicore Processors 11/7/17

Multithreading. Dr. Jens Bennedsen, Aarhus University, School of Engineering Aarhus, Denmark

Object Oriented Programming. Week 10 Part 1 Threads

Threads, Concurrency, and Parallelism

THREADS AND CONCURRENCY

cs Java: lecture #6

Lecture 8: September 30

Grand Central Dispatch and NSOperation. CSCI 5828: Foundations of Software Engineering Lecture 28 12/03/2015

Java Threads and intrinsic locks

Synchronization in Concurrent Programming. Amit Gupta

Java Threads. Introduction to Java Threads

CS11 Java. Fall Lecture 7

Concurrent Computing CSCI 201 Principles of Software Development

CS 2112 Lecture 20 Synchronization 5 April 2012 Lecturer: Andrew Myers

JAVA CONCURRENCY FRAMEWORK. Kaushik Kanetkar

COMP31212: Concurrency A Review of Java Concurrency. Giles Reger

Virtual Machine Design

Produced by. Design Patterns. MSc in Computer Science. Eamonn de Leastar

Synchronized Methods of Old Versions of Java

Chapter 32 Multithreading and Parallel Programming

Writing Parallel Programs COMP360

Reintroduction to Concurrency

CSCI 136 Written Exam #1 Fundamentals of Computer Science II Spring 2015

Module 10A Lecture - 20 What is a function? Why use functions Example: power (base, n)

[module lab 2.2] GUI FRAMEWORKS & CONCURRENCY

[module lab 1.3] CANCELLATION AND SHUTDOWN

Process Scheduling. Copyright : University of Illinois CS 241 Staff

JAVA. Lab 12 & 13: Multithreading

Concurrency. Fundamentals of Computer Science

Threads Questions Important Questions

By: Abhishek Khare (SVIM - INDORE M.P)

Programming Language Concepts: Lecture 11

CS61B, Spring 2003 Discussion #17 Amir Kamil UC Berkeley 5/12/03

Java Concurrency in practice Chapter 9 GUI Applications

Recap. Contents. Reenterancy of synchronized. Explicit Locks: ReentrantLock. Reenterancy of synchronise (ctd) Advanced Thread programming.

Overview. CMSC 330: Organization of Programming Languages. Concurrency. Multiprocessors. Processes vs. Threads. Computation Abstractions

Copyright 2013 Thomas W. Doeppner. IX 1

Producer/Consumer CSCI 201 Principles of Software Development

Midterm assessment - MAKEUP Fall 2010

CMSC421: Principles of Operating Systems

Transcription:

COMP 213 Advanced Object-oriented Programming Lecture 23 Shared Variables and Synchronization

Communicating Threads In the previous lecture, we saw an example of a multi-threaded program where three threads shared one instance of a Queue class. Sharing variables or instances is the most common way for concurrent programs to communicate certainly for multithreaded programs. For example, in the Producer-Consumers example, the shared queue allowed the producer to communicate values to the consumers.

Shared Variables Even though threads might be sharing an instance rather than a variable, we nevertheless describe this situation as communication through shared variables. (The terminology was introduced before object-orientation was common.) Even though the three threads in the Producer-Consumers example might store a reference to the queue in different variables, all these variables point to the same instance.

Shared Variables At a slightly more abstract level, we can think of different threads sharing some common resource. Although this might seem like a very straightforward and innocuous situation, there are pitfalls that can trap the unwary programmer. To introduce these pitfalls, we look at a program where two threads repeatedly print messages to standard output. (Adapted from Wigglesworth & McMillan, Java Programming, Thomson, 2004.)

Shared Variables At a slightly more abstract level, we can think of different threads sharing some common resource. Although this might seem like a very straightforward and innocuous situation, there are pitfalls that can trap the unwary programmer. To introduce these pitfalls, we look at a program where two threads repeatedly print messages to standard output. (Adapted from Wigglesworth & McMillan, Java Programming, Thomson, 2004.)

The MessagePrinter Class Class MessagePrinter instances will run in a Thread and repeatedly print a given message to standard output. class MessagePrinter implements Runnable { private String msg; MessagePrinter(String s) { msg = s;

The MessagePrinter Class Class MessagePrinter instances will run in a Thread and repeatedly print a given message to standard output. class MessagePrinter implements Runnable { private String msg; MessagePrinter(String s) { msg = s;

The MessagePrinter Class Class MessagePrinter instances will run in a Thread and repeatedly print a given message to standard output. class MessagePrinter implements Runnable { private String msg; MessagePrinter(String s) { msg = s;

The run() Method class MessagePrinter, contd. public void run() { for (int i = 0; i < 2000; i++) { for (int j = 0; j < msg.length(); j++) { System.out.print(msg.charAt(j)); System.out.print("\n"); Print the string character-by-character Repeat 2000 times

The run() Method class MessagePrinter, contd. public void run() { for (int i = 0; i < 2000; i++) { for (int j = 0; j < msg.length(); j++) { System.out.print(msg.charAt(j)); System.out.print("\n"); Print the string character-by-character Repeat 2000 times

The run() Method class MessagePrinter, contd. public void run() { for (int i = 0; i < 2000; i++) { for (int j = 0; j < msg.length(); j++) { System.out.print(msg.charAt(j)); System.out.print("\n"); Print the string character-by-character Repeat 2000 times

The main() Method class MessagePrinter, contd. public static void main(string[] args) { MessagePrinter mp1 = new MessagePrinter("Hello, world"); MessagePrinter mp2 = new MessagePrinter("Goodbye, world"); Thread t1 = new Thread(mp1); Thread t2 = new Thread(mp2); t1.start(); t2.start();

Hello, world Hello, world Hello, worglodo dhbeylel,o,w owrolrdl dg ohoedlblyoe wwoorrlldd HGeololdob,y ew,o rwlodr lhde lglooo,d bwyoer,l dw ohrelldl og,o owdobryled, Output terminal output This output was actually obtained using an old version of Java, where threads quanta were much shorter than in the current version.

Controlling Shared Resources The problem here is that both threads want access to the shared resource of System.out. When each threads gets access to System.out, it prints out a string character by character. The time-slicing implemented by the Java virtual machine means that the running thread will probably be put back in the ready-pool before it s printed out its entire message. The result is scrambled messages appearing on standard output.

Interference This is an example of interference: definition of interference data-corruption that occurs when two or more threads share some resource. Interference is a common problem in concurrent programming, and various techniques exist to avoid this problem.

Critical Sections A critical section is a part of a program that should not be interrupted by time-slicing. That is, when a thread enters (starts executing) a critical section, no other thread should be allowed to enter that critical section before the first thread has finished executing the critical section. In our example, we want the code that prints an entire message to be a critical section.

Critical Sections A critical section is a part of a program that should not be interrupted by time-slicing. That is, when a thread enters (starts executing) a critical section, no other thread should be allowed to enter that critical section before the first thread has finished executing the critical section. In our example, we want the code that prints an entire message to be a critical section.

Critical Sections A critical section is a part of a program that should not be interrupted by time-slicing. That is, when a thread enters (starts executing) a critical section, no other thread should be allowed to enter that critical section before the first thread has finished executing the critical section. In our example, we want the code that prints an entire message to be a critical section.

Monitors In the 1950s, Tony Hoare introduced the notion of a monitor as a solution to the problem of critical sections. A monitor can be thought of as a lock that has only one key, and that shuts off the critical section. Before a thread enters a critical section, it must first get the key to the lock. Once it gets the key, it enters the critical section, and keeps the key until it has finished. On leaving the critical section, it gives back the key so that other threads can enter the critical section.

Monitors In the 1950s, Tony Hoare introduced the notion of a monitor as a solution to the problem of critical sections. A monitor can be thought of as a lock that has only one key, and that shuts off the critical section. Before a thread enters a critical section, it must first get the key to the lock. Once it gets the key, it enters the critical section, and keeps the key until it has finished. On leaving the critical section, it gives back the key so that other threads can enter the critical section.

Monitors In the 1950s, Tony Hoare introduced the notion of a monitor as a solution to the problem of critical sections. A monitor can be thought of as a lock that has only one key, and that shuts off the critical section. Before a thread enters a critical section, it must first get the key to the lock. Once it gets the key, it enters the critical section, and keeps the key until it has finished. On leaving the critical section, it gives back the key so that other threads can enter the critical section.

Monitors In the 1950s, Tony Hoare introduced the notion of a monitor as a solution to the problem of critical sections. A monitor can be thought of as a lock that has only one key, and that shuts off the critical section. Before a thread enters a critical section, it must first get the key to the lock. Once it gets the key, it enters the critical section, and keeps the key until it has finished. On leaving the critical section, it gives back the key so that other threads can enter the critical section.

Monitors in Java Java allows critical sections to be protected by monitors, by using the keyword synchronized: synchronized(object) { // critical section goes here keyword synchronized where Object is a reference to an instance of any class.

Monitors in the Interpreter The effect of this is: the interpreter creates a monitor for the code in the synchronized block; it assigns the key to the Object; before a running thread can enter the critical section, it must obtain the key from that object; if the key is not available, the thread is put back in the ready-pool; if that thread is later chosen to run, it must obtain the key before entering the critical section (otherwise back to the pool);

Monitors in the Interpreter The effect of this is: the interpreter creates a monitor for the code in the synchronized block; it assigns the key to the Object; before a running thread can enter the critical section, it must obtain the key from that object; if the key is not available, the thread is put back in the ready-pool; if that thread is later chosen to run, it must obtain the key before entering the critical section (otherwise back to the pool);

Monitors in the Interpreter The effect of this is: the interpreter creates a monitor for the code in the synchronized block; it assigns the key to the Object; before a running thread can enter the critical section, it must obtain the key from that object; if the key is not available, the thread is put back in the ready-pool; if that thread is later chosen to run, it must obtain the key before entering the critical section (otherwise back to the pool);

Monitors in the Interpreter The effect of this is: the interpreter creates a monitor for the code in the synchronized block; it assigns the key to the Object; before a running thread can enter the critical section, it must obtain the key from that object; if the key is not available, the thread is put back in the ready-pool; if that thread is later chosen to run, it must obtain the key before entering the critical section (otherwise back to the pool);

Monitors in the Interpreter The effect of this is: the interpreter creates a monitor for the code in the synchronized block; it assigns the key to the Object; before a running thread can enter the critical section, it must obtain the key from that object; if the key is not available, the thread is put back in the ready-pool; if that thread is later chosen to run, it must obtain the key before entering the critical section (otherwise back to the pool);

Monitors in the Interpreter once a running thread obtains the key, it keeps it until it has finished executing the synchronized block, at which point the key becomes available to other threads; if a thread has a key, it keeps it even in the ready-pool and the blocked-pool. Note that this entire process is managed by the interpreter: all the programmer does is specify the synchronized block and the object that keeps the key.

Monitors in the Interpreter once a running thread obtains the key, it keeps it until it has finished executing the synchronized block, at which point the key becomes available to other threads; if a thread has a key, it keeps it even in the ready-pool and the blocked-pool. Note that this entire process is managed by the interpreter: all the programmer does is specify the synchronized block and the object that keeps the key.

Monitors in the Interpreter once a running thread obtains the key, it keeps it until it has finished executing the synchronized block, at which point the key becomes available to other threads; if a thread has a key, it keeps it even in the ready-pool and the blocked-pool. Note that this entire process is managed by the interpreter: all the programmer does is specify the synchronized block and the object that keeps the key.

Monitors and MessagePrinters In our example, we ll synchronize the block of code that prints a message to standard output. This means that only one thread at a time can execute that code. The choice of an object to keep the key is pretty much arbitrary; we ll create an instance of the Integer class for this purpose.

The Key-Keeper class MessagePrinter v2 class MessagePrinter implements Runnable { private String msg; private static Integer lock = new Integer(0); MessagePrinter(String s) { msg = s; This will be the key-keeper This is a class field, so all instances of MessagePrinter share the same key-keeper

The Key-Keeper class MessagePrinter v2 class MessagePrinter implements Runnable { private String msg; private static Integer lock = new Integer(0); MessagePrinter(String s) { msg = s; This will be the key-keeper This is a class field, so all instances of MessagePrinter share the same key-keeper

The Key-Keeper class MessagePrinter v2 class MessagePrinter implements Runnable { private String msg; private static Integer lock = new Integer(0); MessagePrinter(String s) { msg = s; This will be the key-keeper This is a class field, so all instances of MessagePrinter share the same key-keeper

In the run() Method in MessagePrinter#run() synchronized(lock) { for (int j=0; j<msg.length(); j++) { System.out.print(msg.charAt(j)); try { Thread.sleep(10); catch (InterruptedException e) { System.out.print("\n"); Critical section: any Thread has to get the key from lock before running this

In the run() Method in MessagePrinter#run() synchronized(lock) { for (int j=0; j<msg.length(); j++) { System.out.print(msg.charAt(j)); try { Thread.sleep(10); catch (InterruptedException e) { System.out.print("\n"); Critical section: any Thread has to get the key from lock before running this

Notes Note we ve added a call to sleep() in this method. The effect of this is to make a fair interleaving of the two threads more likely. The main reason we ve added this call to sleep(), however, is to show that the interpreter s implementation of monitors still works even when a thread is certain to be taken out of the running in the middle of the critical section.

The Output Hello, world Hello, world Goodbye, world Hello, world Goodbye, world Hello, world Goodbye, world terminal output

Non-Static Key-keepers Recall that we made the field lock static: private static Integer lock = new Integer(0); Earlier versions of Java used to require that Key-keepers could not contain any non-static references. The compiler would give an error message if we left out the static modifier from the declaration of lock. In Java 1.6, if we remove the static modifier, private Integer lock = new Integer(0); the code will compile, but it is a semantic error.

Non-Static Key-keepers Recall that we made the field lock static: private static Integer lock = new Integer(0); Earlier versions of Java used to require that Key-keepers could not contain any non-static references. The compiler would give an error message if we left out the static modifier from the declaration of lock. In Java 1.6, if we remove the static modifier, private Integer lock = new Integer(0); the code will compile, but it is a semantic error.

Key-Keepers should be Unique If we have a non-static field lock keeping the key to the critical section, then each instance of MessagePrinter would have its own key-keeper for the critical section. The result would be that each thread would have its own instance of MessagePrinter, and each instance of MessagePrinter would have its own key-keeper for the critical section. Obtaining the key for the critical section would be trivial: each thread would go through its own key-keeper. The result would be again scrambled messages.

Key-Keepers should be Unique Similarly, consider: synchronized(new Integer(0)) { for (int j=0; j<msg.length(); j++) { System.out.print(msg.charAt(j)); try { Thread.sleep(10); catch (InterruptedException e) { System.out.print("\n");

Key-Keepers should be Unique In this case, each time the code is executed, a new key-keeper will be created. Again, the result is scrambled messages. Generally, the best approach is to use a static field for the key-keeper.

Threads and GUIs One of the main reasons for using multithreaded programming is to allow a user to continue interacting with an application while some (lengthy) computation is in progress. For applications with a GUI, it may be important and it will probably be desirable to let users interact with the GUI while event-handling code (from a previous interaction) is being executed.

Threads and GUIs One of the main reasons for using multithreaded programming is to allow a user to continue interacting with an application while some (lengthy) computation is in progress. For applications with a GUI, it may be important and it will probably be desirable to let users interact with the GUI while event-handling code (from a previous interaction) is being executed.

Threads and GUIs We ll look at the following questions: How is event-handling code executed? Does the programmer need to create threads? Can GUI components suffer from interference?

How is Event-Handling Code Executed? When the Java interpreter starts up, there is one thread, main, that executes the main() method. For GUIs, the main() method typically creates and displays a Frame; all further computation is then driven by component-generated event (button-clicks, etc.). The main thread terminates (dies), and this would normally mean that the Java interpreter would exit. However...

How is Event-Handling Code Executed? When an AWT or swing Frame is created, a special thread is created by the Java interpreter to handle component-generated events and their event-handling code. This thread is called the Event-Dispatch Thread. All event-handling code is executed in this thread (i.e., all the actionperformed(), etc., methods). The Event-dispatch Thread terminates when all Frames have been closed.

Does the Programmer Need to Create Threads? No. By default, the Event-Dispatch Thread will be used to execute all event-handling code. However, there may be occasions when it s desirable to create a separate thread for lengthy event-handling code (e.g., reading a large file across a network).

Does the Programmer Need to Create Threads? No. By default, the Event-Dispatch Thread will be used to execute all event-handling code. However, there may be occasions when it s desirable to create a separate thread for lengthy event-handling code (e.g., reading a large file across a network).

Does the Programmer Need to Create Threads? No. By default, the Event-Dispatch Thread will be used to execute all event-handling code. However, there may be occasions when it s desirable to create a separate thread for lengthy event-handling code (e.g., reading a large file across a network).

Can GUI Components Suffer from Interference? If only the Event-Dispatch thread is used: no. (Interference is when data corruption arises from more than one thread accessing a shared resource.) If the programmer has explicitly created new threads in the event-handling code, and these threads access a shared resource (e.g., a TextArea): yes, interference is a possibility.

Thread-Safety A component is thread-safe if its methods are synchronized to prevent interference. Most components in the AWT package are thread-safe; most components in the swing package are not thread-safe. So if you create threads in event-handling code, take care!

How Many Threads Do You Need? Java uses one thread to handle all user interaction with a GUI. This makes sense, because most responses to user interactions can be done quickly (save a file, modify/bring up a new GUI element, etc.); but creating and maintaining threads uses a lot of time and memory There are many situations where a program needs to handle a lot of requests for tasks that can be handled quickly. Typical examples are GUIs and servers. For example, web servers may receive many requests in a short period; but each request takes only a short time to handle (get the file; send it). In such cases, it makes sense to use a small number of threads to do all the work.

How Many Threads Do You Need? Java uses one thread to handle all user interaction with a GUI. This makes sense, because most responses to user interactions can be done quickly (save a file, modify/bring up a new GUI element, etc.); but creating and maintaining threads uses a lot of time and memory There are many situations where a program needs to handle a lot of requests for tasks that can be handled quickly. Typical examples are GUIs and servers. For example, web servers may receive many requests in a short period; but each request takes only a short time to handle (get the file; send it). In such cases, it makes sense to use a small number of threads to do all the work.

How Many Threads Do You Need? Java uses one thread to handle all user interaction with a GUI. This makes sense, because most responses to user interactions can be done quickly (save a file, modify/bring up a new GUI element, etc.); but creating and maintaining threads uses a lot of time and memory There are many situations where a program needs to handle a lot of requests for tasks that can be handled quickly. Typical examples are GUIs and servers. For example, web servers may receive many requests in a short period; but each request takes only a short time to handle (get the file; send it). In such cases, it makes sense to use a small number of threads to do all the work.

How Many Threads Do You Need? Java uses one thread to handle all user interaction with a GUI. This makes sense, because most responses to user interactions can be done quickly (save a file, modify/bring up a new GUI element, etc.); but creating and maintaining threads uses a lot of time and memory There are many situations where a program needs to handle a lot of requests for tasks that can be handled quickly. Typical examples are GUIs and servers. For example, web servers may receive many requests in a short period; but each request takes only a short time to handle (get the file; send it). In such cases, it makes sense to use a small number of threads to do all the work.

One Thread Does It All Writing a thread to perform many tasks might go like this: hard-working thread pseudocode class Worker implements Runnable { public void run() { while (stillneeded) { get next task do it Run this in a thread, and that thread will execute many tasks.

What To Do In this context a task is just some Java code e.g., in the case of GUIs, the event-handling code for saving a file, bringing up a new GUI element, etc., or, in the case of a server, getting and transmitting a file, etc. How can we treat such snippets of code tasks in a generic way? Interfaces! Let s say a task is an instance of some class that implements Runnable (i.e., a task is whatever code is contained in such an instance s run() method).

What To Do In this context a task is just some Java code e.g., in the case of GUIs, the event-handling code for saving a file, bringing up a new GUI element, etc., or, in the case of a server, getting and transmitting a file, etc. How can we treat such snippets of code tasks in a generic way? Interfaces! Let s say a task is an instance of some class that implements Runnable (i.e., a task is whatever code is contained in such an instance s run() method).

This lets us give a bit more detail: How To Do It class Worker implements Runnable { public void run() { Runnable r; while (stillneeded) { // get next task r = next task // do it r.run(); hard-working thread pseudocode

What To Do If we have a lot of tasks, how can we make them available to our hard-working thread to execute? We can put them onto a Queue, then create some number of Worker threads that repeatedly get tasks from the Queue and execute them. in some main method, somewhere Queue<Runnable> jobs = new Queue<Runnable>(); for (int i = 0; i < 200; i++) { jobs.add(new MessagePrinter("task" + i));

What To Do If we have a lot of tasks, how can we make them available to our hard-working thread to execute? We can put them onto a Queue, then create some number of Worker threads that repeatedly get tasks from the Queue and execute them. in some main method, somewhere Queue<Runnable> jobs = new Queue<Runnable>(); for (int i = 0; i < 200; i++) { jobs.add(new MessagePrinter("task" + i));

How To Do It Back to our hard-working thread: it should read its next task to execute from the queue: class Worker implements Runnable { private Queue<Runnable> tasks; public Worker(Queue<Runnable> q) { tasks = q; hard-working thread code

How To Do It Back to our hard-working thread: it should read its next task to execute from the queue: class Worker implements Runnable { private Queue<Runnable> tasks; public Worker(Queue<Runnable> q) { tasks = q; hard-working thread code

How To Do It hard-working thread pseudocode, contd. public void run() { Runnable r; while (stillneeded) { r = tasks.getnext(); r.run(); Our hard-working threads are Consumers. They repeatedly read tasks from a queue and execute them. (This gives a hint how to implement the stillneeded part.)

How To Do It hard-working thread pseudocode, contd. public void run() { Runnable r; while (stillneeded) { r = tasks.getnext(); r.run(); Our hard-working threads are Consumers. They repeatedly read tasks from a queue and execute them. (This gives a hint how to implement the stillneeded part.)

What To Do What about the Producer? in some main method, somewhere Queue<Runnable> jobs = new Queue<Runnable>(); for (int i = 0; i < 200; i++) { jobs.add(new MessagePrinter("task" + i)); for (int i = 0; i < 5; i++) { new Worker(jobs).start(); Create 5 threads to consume/execute the tasks and start them running

What To Do What about the Producer? in some main method, somewhere Queue<Runnable> jobs = new Queue<Runnable>(); for (int i = 0; i < 200; i++) { jobs.add(new MessagePrinter("task" + i)); for (int i = 0; i < 5; i++) { new Worker(jobs).start(); Create 5 threads to consume/execute the tasks and start them running

What To Do What about the Producer? in some main method, somewhere Queue<Runnable> jobs = new Queue<Runnable>(); for (int i = 0; i < 200; i++) { jobs.add(new MessagePrinter("task" + i)); for (int i = 0; i < 5; i++) { new Worker(jobs).start(); Create 5 threads to consume/execute the tasks and start them running

Wouldn t it be Nice Wouldn t it be nice if someone wrote a class of worker threads that executed any number of tasks concurrently? (and took care of the stillneeded part) Then the programmer need only write the tasks to be executed, and not worry about creating too many threads (which can be expensive in resource use). Someone has. The class is java.util.concurrent.executor

Wouldn t it be Nice Wouldn t it be nice if someone wrote a class of worker threads that executed any number of tasks concurrently? (and took care of the stillneeded part) Then the programmer need only write the tasks to be executed, and not worry about creating too many threads (which can be expensive in resource use). Someone has. The class is java.util.concurrent.executor

Class java.util.concurrent Class Executors has static methods newfixedthreadpool and newcachedthreadpool that return an ExecutorService instance. An ExecutorService is an object that has a void method execute(runnable). newfixedthreadpool() creates a pool consisting of a fixed number of worker threads that will execute the given tasks. newcachedthreadpool() also creates a pool of threads that will execute the given tasks. When a task is to be executed, an existing thread in the pool will be used, if one is available; if no thread is available, a new one will be created.

Class java.util.concurrent Class Executors has static methods newfixedthreadpool and newcachedthreadpool that return an ExecutorService instance. An ExecutorService is an object that has a void method execute(runnable). newfixedthreadpool() creates a pool consisting of a fixed number of worker threads that will execute the given tasks. newcachedthreadpool() also creates a pool of threads that will execute the given tasks. When a task is to be executed, an existing thread in the pool will be used, if one is available; if no thread is available, a new one will be created.

Using Executors ExecutorService workers = Executors.newFixedThreadPool(5); the previous example, redone for (int i = 0; i < 200; i++) { workers.execute( new MessagePrinter("task" + i)); workers.shutdown(); Create a pool of five worker threads have the worker threads execute 200 tasks Make the threads stop...

Using Executors ExecutorService workers = Executors.newFixedThreadPool(5); the previous example, redone for (int i = 0; i < 200; i++) { workers.execute( new MessagePrinter("task" + i)); workers.shutdown(); Create a pool of five worker threads have the worker threads execute 200 tasks Make the threads stop...

Using Executors ExecutorService workers = Executors.newFixedThreadPool(5); the previous example, redone for (int i = 0; i < 200; i++) { workers.execute( new MessagePrinter("task" + i)); workers.shutdown(); Create a pool of five worker threads have the worker threads execute 200 tasks Make the threads stop...

shutdown Method shutdown() in interface ExecutorService causes the worker threads to terminate once all tasks in the queue have been read and executed. Method shutdownnow() in interface ExecutorService causes the worker threads stop reading new tasks from the queue, and to terminate once all tasks that are currently being executed have terminated. Using shutdownnow() might mean that not all tasks get executed.

shutdown Method shutdown() in interface ExecutorService causes the worker threads to terminate once all tasks in the queue have been read and executed. Method shutdownnow() in interface ExecutorService causes the worker threads stop reading new tasks from the queue, and to terminate once all tasks that are currently being executed have terminated. Using shutdownnow() might mean that not all tasks get executed.

shutdown Method shutdown() in interface ExecutorService causes the worker threads to terminate once all tasks in the queue have been read and executed. Method shutdownnow() in interface ExecutorService causes the worker threads stop reading new tasks from the queue, and to terminate once all tasks that are currently being executed have terminated. Using shutdownnow() might mean that not all tasks get executed.

Summary Interference Critical Sections Monitors Synchronization Next: Synchronization and deadlock