Der Java-Experten-Kurs Threads, GUI, EventQueue
Karl Pauls
Verklemmungserkennung private static final Object mutex1 = new Object(); private static final Object mutex2 = new Object(); final Thread t1 = new Thread(){ { start(); } public void run(){ synchronized(mutex1){ Thread.sleep(1000000); synchronized(mutex2){}}}}; final Thread t2 = new Thread(){ {start();} public void run(){ synchronized(mutex2){ t1.interrupt(); synchronized(mutex1){}}}};
Verklemmungserkennung CTRL-BREAK (Windows) CTRL-\ (Unix) Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x180ff00 (object 0x65055aa8, a java.lang.Object), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x180ff24 (object 0x65055ab0, a java.lang.Object), which is held by "Thread-1" Java stack information for the threads listed above: =================================================== "Thread-1": at s8.g0.BreakMain$2.run(BreakMain.java:49) - waiting to lock (a java.lang.Object) - locked (a java.lang.Object) "Thread-0": at s8.g0.BreakMain$1.run(BreakMain.java:29) - waiting to lock (a java.lang.Object) - locked (a java.lang.Object) Found 1 deadlock.
Daemons :-) Thread t = new Thread(); t.setDaemon(true); => Hält VM NICHT am Leben final Thread t1 = new Thread(){ { setDaemon(true); start(); } …} final Thread t2 = new Thread(){ {setDaemon(true); start(); } …}
=> Terminiert! setDaemon() immer vor start()
Exceptions und Threads
Was ist mit dem Thread
Tja Tot
Aber wie kann man solche Exceptions behandeln?
Lösung: ThreadGroups
Exception handling 1
Tip: Ownerless Dialogs
Exception handling 2 Java 5:
Thread.setDefaultUncaughtExceptionHandler( new DefaultExceptionHandler());
Swing thread In Swing, all GUI components have to be changed from within the Swing thread. jLabelFoo.setText(”bar") ist Verboten (wenn nicht im SwingT.) ! SwingUtilities.invokeLater(new Runnable() { public void run() { jLabel1.setText(”bar"); } } Oder: SwingUtilities.invokeAndWait(…)
Swing thread (cond.) Swing thread bedeutet entweder: in einem callback (z.B.: ActionListener) Oder: SwingUtilities.isEventDispatchThread()
Sonst: refresh problems DEADLOCK
EventQueue EventQueue is a platform-independent class that queues events, both from the underlying peer classes and from trusted application classes. It encapsulates asynchronous event dispatch machinery which extracts events from the queue and dispatches them by calling dispatchEvent(AWTEvent) method on this EventQueue with the event to be dispatched as an argument. The particular behavior of this machinery is implementation-dependent. The only requirements are that events which were actually enqueued to this queue (note that events being posted to the EventQueue can be coalesced) are dispatched: Sequentially. That is, it is not permitted that several events from this queue are dispatched simultaneously. In the same order as they are enqueued. That is, if AWTEvent A is enqueued to the EventQueue before AWTEvent B then event B will not be dispatched before event .
EventQueue
Eigene EventQueue import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MyEventQueue extends EventQueue { protected void dispatchEvent(AWTEvent event) { System.out.println(event); super.dispatchEvent(event); } } Toolkit.getDefaultToolkit().getSystemEventQueue().push( new MyEventQueue());
Eigene EventQueue Demo new JFrame("test").setVisible(true); =>
sun.awt.PeerEvent[INVOCATION_DEFAULT,runnable=apple.awt.EventFactoryProxy$2@cac268,notifier java.awt.event.ComponentEvent[COMPONENT_RESIZED (0,22 128x15)] on javax.swing.JRootPane[,0,2 java.awt.event.ComponentEvent[COMPONENT_MOVED (0,22 128x15)] on javax.swing.JRootPane[,0,22 java.awt.event.WindowEvent[WINDOW_GAINED_FOCUS,opposite=null,oldState=0,newState=0] on fram java.awt.event.WindowEvent[WINDOW_ACTIVATED,opposite=null,oldState=0,newState=0] on frame0 sun.awt.PeerEvent[INVOCATION_DEFAULT,runnable=apple.awt.EventFactoryProxy$2@f72617,notifier= java.awt.event.ComponentEvent[COMPONENT_SHOWN] on frame0 java.awt.SentEvent[] on apple.awt.CToolkit@dc8569 java.awt.event.WindowEvent[WINDOW_OPENED,opposite=null,oldState=0,newState=0] on frame0 java.awt.event.FocusEvent[FOCUS_GAINED,permanent,opposite=null] on frame0 java.awt.event.PaintEvent[PAINT,updateRect=java.awt.Rectangle[x=0,y=22,width=128,height=15]] on f java.awt.event.PaintEvent[UPDATE,updateRect=java.awt.Rectangle[x=0,y=0,width=128,height=37]] on java.awt.event.WindowEvent[WINDOW_LOST_FOCUS,opposite=null,oldState=0,newState=0] on frame java.awt.event.FocusEvent[FOCUS_LOST,temporary,opposite=null] on frame0 java.awt.event.WindowEvent[WINDOW_DEACTIVATED,opposite=null,oldState=0,newState=0] on frame java.awt.SentEvent[] on apple.awt.CToolkit@dc8569 java.awt.SentEvent[] on apple.awt.CToolkit@dc8569
Hotkey Manager
Hotkey ManagerTest
Timer (1) private final javax.swing.Timer timer = new javax.swing.Timer(true); Action updateCursorAction = new AbstractAction() { boolean shouldDraw = false; public void actionPerformed(ActionEvent e) { if (shouldDraw = !shouldDraw) { # drawCursor(); } else { eraseCursor();} }}; new Timer(300, updateCursorAction).start();
Timer (2) private final java.util.Timer timer = new java.util.Timer(true); final Runnable doUpdateCursor = new Runnable() { private boolean shouldDraw = false; public void run() { if (shouldDraw = !shouldDraw) { drawCursor(); } else { eraseCursor();} }}; TimerTask updateCursorTask = new TimerTask() { public void run() { EventQueue.invokeLater(doUpdateCursor); }}; myGlobalTimer.schedule(updateCursorTask, 0, 300);
Mögliche Aufgaben • Entwicklung einer EventQueue, die Alarm gibt wenn eine Aktion länger dauert (i.e., die GUI blockiert) • Entwicklung einer EventQueue, die Automatisch die GUI blockiert wärend eine Aktion ausgeführt wird • EventQueue / Exception handler kombination welche die die letzten Aktionen zusammen mit der Exception ausgibt.