Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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; }