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;
}