Concurrency (p2) - Rice University
Download
Report
Transcript Concurrency (p2) - Rice University
Concurrency (p2)
synchronized (this) {
doLecture(part2);
}
Quick Review
Threads can up performance
Java’s 2 parts for thread safety
Atomicity
Visibility
Java’s Primitives
volatile
synchronized
Library Support
Atomic variables
Concurrent collections
Common synchronizers (BlockingQueue)
Outline
Executor Framework
Shutdown and cancellation
Swing and Concurrency
Custom Synchronizers
Starting Threads
Executor framework
public interface Executor {
void execute(Runnable command);
}
Executor Example
class MyTask implements Runnable {
public void run() {…}
public static void main(…) {
Runnable task1 = new MyTask();
Executor exec = /* */;
exec.execute(task1);
}
}
1 Thread/ Task
class OnePer implements Executor {
public void Execute(Runnable r){
new Thread(r).start();
}
}
Single Threaded
class Just1 implements Executor {
public void Execute(Runnable r){
r.run();
}
}
Provided Thread Pool
Executors
newFixedThreadPool
Bounded size
Replace if thread dies
newCachedThreadPool
Demand driven variable size
newSingleThreadExecutor
Just one thread
Replace if thread dies
newScheduledThreadPool
Delayed and periodic task execution
Good replacement for class Timer
Executor Shut-down
Executor is a serice provider
Executor abstracts thread
management
To maintain the abstraction, the
service should generally provide
methods for shutting down the
service
JVM cannot shut down until threads
do
ExecutorService
public
interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean
awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
}
ExecutorService Notes
Implies three states:
Running
Shutting down
Terminated
shutdown() runs tasks in queue
shutdownNow() returns unstarted
tasks
awaitTermination() blocks
until the service is in the
terminated state
ExecutorService
implementation
ExecutorService is an interface
How do you implement shut
down and cancellation?
Cancellation in Java
Cooperative, not mandated
Traditional method: interruption
Public class Thread {
public void interrupt();
public void isInterrupted();
public static boolean interrupted();
…
}
Interruption
Just a request!
Sets a flag that must be
explicitly cleared!
Some methods clear the flag &
throw InterruptedException
Others ignore it, leaving other
code to handle it
IMPORTANT!
Your code should follow protocol
when interrupted
If interrupted(),
Throw exception
Reset the flag for other code
If InterruptedException
Pass it along
Reset the flag for other code
Don’t swallow, unless your code is
handles the interruption policy
Restoring Interrupted
Status
catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
// checks (AND CLEARS!) current thread
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
}
Handeling Interruption
Long computations “break” to
check interrupted status
If interrupted, stop
computation, throw
InterruptedException or
restore the interrupted status
Interrupting NonBlocking Operations
Socket read/writes do not
support interruption!
If you detect interruption, close
the socket causing read/write to
throw an exception
Locks (via synchronized) can
not be interrupted
Explicit locks beyond scope of
this lecture
Future
Interface representing the
lifecycle of a task
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException,
ExecutionException, CancellationException
V get() throws InterruptedException,
ExecutionException, CancellationException,
TimeoutException
}
CompletionService
Combines Executor with
BlockingQueue
ExecutorCompletionService
public interface CompletionService<V> {
Future<V> poll();
Future<V> poll(long timeout, TimeUnit unit);
Future<V> submit(Callable<V> task);
Future<V> submit(Runnable<V> task);
Future<V> take();
}
Futures Again
ExecutorService interface also
provides
public interface ExecutorService {
…
Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
Future<T> submit(Runnable task, T result);
}
GUI’s
Are almost always single
threaded
That is, they have a dedicated
thread for the GUI, but just 1!
Multithreaded has been tried,
but has generally failed
Event Processing
The Swing apps expect short
events that can be processed
quickly in sequence
So, long running operations must
be executed in another thread
Swing troubles are often related to
communication between these
threads
Swing Manipulation
Swing does NOT use
synchronization, it uses thread
confinement
You should almost NEVER
create, modify, or query swing
components or data models
outside the event-dispatching
thread
(A Few Exceptions)
Some components (see JavaDoc)
SwingUtilities.isEventDispatchThrea
d
SwingUtilities.invokeLater
SwingUtilities.invokeAndWait
Methods to enqueue repaint or
revalidation
Methods for add/remove listeners
Short-running Tasks
Short, GUI-confined operations
can be programmed entirely in
the EDThread
Trivial Example: button that
changes color when clicked
Example: information between
model and view
Long-running Tasks
Proposed Handling:
GuiExecutor
newCachedThreadPool
GuiExecutor
import java.util.*;
import java.util.concurrent.*;
public class GuiExecutor extends AbstractExecutorService {
// Singletons have a private constructor and a public factory
private static final GuiExecutor instance = new GuiExecutor();
private GuiExecutor() {}
public static GuiExecutor instance() { return instance; }
public void execute(Runnable r) {
if (SwingUtilities.isEventDispatchThread())
r.run();
else
SwingUtilities.invokeLater(r);
}
/* shutdown, shutdownNow, and awaitTermination throw
UnsupportedOperationException for now */
public boolean isShutdown() {return false;
public boolean isTerminated() {return false;
}
}
}
Long Running Tasks:
Starting
Fire off tasks to thread pool
When completed, use the
GuiExecutor to send a task for
updating gui
Simple example: status text
Long-running Tasks:
Cancellation
Instead of execute(), use
submit()
Returns a Future<V> that is
cancelable
You still have to make your
task interruptable
Long-running Tasks:
Visual Feedback
The books method:
Create a task subclass with some
methods callable from EDthread,
& others callable elsewhere
I think this is dangerous. If
you’re going to do this, you
should
Clearly document the methods
Check if you’re in the Edthread
BackgroundTask<V>
Code is confusing, hard to follow
If you want to look at it:
www.javaconcurrencyinpractice.com/listings/BackgroundTask.java
Simpler Solution
Design LR tasks with “hooks”
The hook can be a special
communication class
When checking for
cancellation, update the hook
Hook schedules update to GUI
Last Notes
Writing your own synchronizers
// BLOCKS-UNTIL: not-full
public synchronized void put(V v) throws InterruptedException {
while (isFull())
wait();
doPut(v);
notifyAll();
}
// BLOCKS-UNTIL: not-empty
public synchronized V take() throws InterruptedException {
while (isEmpty())
wait();
V v = doTake();
notifyAll();
return v;
}