10

I have a Java program which executes a tight loop on a separate (non-EDT) thread. Although I would think the Swing UI should still be responsive, it is not. The example program below exhibits the problem: clicking the "Try me" button should pop up a dialog more-or-less half a second later, and it should be possible to close that dialog immediately by clicking any of its responses. Instead, the dialog takes much longer to appear, and/or takes a long time to close after clicking one of the buttons.

  • Problem occurs on Linux (two different machines with different distributions), on Windows, on the Raspberry Pi (server VM only) and on Mac OS X (reported by another SO user).
  • Java version 1.8.0_65 and 1.8.0_72 (tried both)
  • i7 processor with many cores. The EDT should have plenty of spare processing power available.

Does anyone have any idea why the EDT processing is being delayed, even though there is only a single busy thread?

(Please note that despite various suggestions of the Thread.sleep call being the cause of the problem, it is not. It can be removed and the problem can still be reproduced, though it manifests slightly less frequently and usually exhibits the second behavior described above - i.e. non-responsive JOptionPane dialog rather than delayed dialog appearance. Furthermore, there is no reason that the sleep call should yield to the other thread because there are spare processor cores as mentioned above; the EDT could continue to run on another core after the call to sleep).

import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class MFrame extends JFrame
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(() -> {
            new MFrame();
        });
    }

    public MFrame()
    {
        JButton tryme = new JButton("Try me!");

        tryme.addActionListener((e) -> {
            Thread t = new Thread(() -> {
                int a = 4;
                for (int i = 0; i < 100000; i++) {
                    for (int j = 0; j < 100000; j++) {
                        a *= (i + j);
                        a += 7;
                    }
                }
                System.out.println("a = " + a);
            });

            t.start();

            // Sleep to give the other thread a chance to get going.
            // (Included because it provokes the problem more reliably,
            // but not necessary; issue still occurs without sleep call).
            try {
                Thread.sleep(500);
            }
            catch (InterruptedException ie) {
                ie.printStackTrace();
            }

            // Now display a dialog
            JOptionPane.showConfirmDialog(null, "You should see this immediately");
        });

        getContentPane().add(tryme);

        pack();
        setVisible(true);
    }
}

Update: The problem occurs only with the server VM (but see further update). Specifying the client VM (-client command line argument to java executable) seems to suppress the problem (update 2) on one machine but not another.

Update 3: I see 200% processor usage by the Java process after clicking the button, implying that there are 2 processor cores fully loaded. This doesn't make sense to me at all.

Update 4: Also occurs on Windows.

Update 5: Using a debugger (Eclipse) proves problematic; the debugger seems unable to stop the threads. This is highly unusual, and I suspect there is some sort of livelock or race condition in the VM, so I've filed a bug with Oracle (review ID JI-9029194).

Update 6: I found my bug report in the OpenJDK bug database. (I was not informed that it had been accepted, I had to search for it). The discussion there is most interesting and already sheds some light on what may be the cause of this problem.

davmac
  • 20,150
  • 1
  • 40
  • 68
  • 1
    It's the `sleep`. The sleep call is yielding to the busy thread. And sleep/wait only guarantee that “at least” the requested amount of time will have passed when they return. – VGR Feb 02 '16 at 13:58
  • 1
    @VGR I don't think so. Did you try? – user1803551 Feb 02 '16 at 14:22
  • Yes. When I comment out the sleep, the JOptionPane appears immediately. (Linux amd64, four cores.) – VGR Feb 02 '16 at 14:22
  • @VGR It appears immediately, but is it responsive? – user1803551 Feb 02 '16 at 14:28
  • @user1803551 Ah… no, it is not responsive. I stand corrected. – VGR Feb 02 '16 at 14:31
  • @VGR yes, sleep guarantees that "at least" the requested amount of time will pass, but I usually see significantly more - in fact, the secondary thread usually completes (and outputs to the console) before the dialog window appears, several seconds later. Why should the EDT processing be delayed at all in this case? There are processor cores to spare. – davmac Feb 02 '16 at 15:26
  • I dont know which IDE you are using, but when I do a lot of System.out.println() my Eclipse get blocked what may also affect other UI applications. – Stephan Feb 02 '16 at 15:53
  • @Stephan please read the question carefully, there is only one line of output which occurs at a very limited rate. FWIW the problem is independent of the IDE and occurs when I run either from Eclipse or from the command line. – davmac Feb 02 '16 at 16:02
  • In your example, you're calling `Thread.sleep` inside the context of the EDT (inside the `ActionListener`) – MadProgrammer Feb 02 '16 at 20:23
  • @MadProgrammer the `Thread.sleep` is not the cause of the issue, as has already been discussed. It merely provokes the problem more reliably (or rather, in a more obvious fashion). – davmac Feb 02 '16 at 21:41
  • @davmac Well, isn't that awesome, I'd either remove it or make a comment in your code about it as it's a major distraction to the apparent problem you're having – MadProgrammer Feb 02 '16 at 22:31
  • @MadProgrammer despite the unnecessarily sarcastic tone of your comment, I've taken your advice and put a comment in the code. Thanks. – davmac Feb 03 '16 at 10:51
  • 1
    @davmac Early morning observations, patience isn't particularly high :P – MadProgrammer Feb 03 '16 at 20:17
  • Thank you for bug report [JDK-8149007](https://bugs.openjdk.java.net/browse/JDK-8149007); very informative. – trashgod Mar 02 '16 at 11:21

5 Answers5

2

I see the same effect to Mac OS X. Although your example is correctly synchronized, the platform/JVM variability you see is likely due to vagaries in how threads are scheduled, resulting is starvation. Adding Thread.yield() to the outer loop in t mitigates the problem, as shown below. Except for the artificial nature of the example, a hint like Thread.yield() would not ordinarily be required. In any case, consider SwingWorker, shown here executing a similarly tight loop for demonstration purposes.

I do not believe that Thread.yield() should need to be called in this case at all, despite the artificial nature of the test case, however.

Correct; yielding simply exposes the underlying problem: t starves the event dispatch thread. Note that the GUI updates promptly in the example below, even without Thread.yield(). As discussed in this related Q&A, you can try lowering the thread's priority. Alternatively, run t in a separate JVM, as suggested here using ProcessBuilder, which can also run in the background of a SwingWorker, as shown here.

but why?

All supported platforms are built on single-threaded graphics libraries. It's fairly easy to block, starve or saturate the governing event dispatch thread. Non-trivial background tasks typically yield implicitly, as when publishing intermediate results, blocking for I/O or waiting on a work queue. A task that does not do may have to yield explicitly.

image

import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MFrame extends JFrame {

    private static final int N = 100_000;
    private static final String TRY_ME = "Try me!";
    private static final String WORKING = "Working…";

    public static void main(String[] args) {
        EventQueue.invokeLater(new MFrame()::display);
    }

    private void display() {
        JButton tryme = new JButton(TRY_ME);
        tryme.addActionListener((e) -> {
            Thread t = new Thread(() -> {
                int a = 4;
                for (int i = 0; i < N; i++) {
                    for (int j = 0; j < N; j++) {
                        a *= (i + j);
                        a += 7;
                    }
                    Thread.yield();
                }
                EventQueue.invokeLater(() -> {
                    tryme.setText(TRY_ME);
                    tryme.setEnabled(true);
                });
                System.out.println("a = " + a);
            });
            t.start();
            tryme.setEnabled(false);
            tryme.setText(WORKING);
        });
        add(tryme);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for confirming. That means the problem can be reliably reproduced on Windows, Linux, Mac OS X and Raspberry Pi (which I've tested in the meantime). I do not believe that `Thread.yield()` should need to be called in this case at all, _despite_ the artificial nature of the test case, however. There are two threads (the EDT and the created thread) which should not be contending for any resources, and there are more than enough spare processor cores to run both of those threads. – davmac Feb 02 '16 at 21:45
  • I've elaborated above. – trashgod Feb 03 '16 at 10:08
  • "t starves the event dispatch thread" - ok, but _why_? There are processor cores to spare, so the EDT could easily run on another core; there shouldn't be any contention between the two threads. And why do I see two threads (presumably `t` and the `EDT`) both consuming 100% of a core? To me this is starting to look like a live-lock problem in the JVM. – davmac Feb 03 '16 at 10:33
  • I'm not sure; I'd focus on why a background task would fail to yield. – trashgod Feb 03 '16 at 17:10
  • 2
    you misunderstand me, I think. There should be no need for it to yield the processor core if there are other cores idle. – davmac Feb 03 '16 at 17:20
  • @davmac While, in theory, that might be true, you're still a victim of how the OS schedules it's threads. There might be a difference in how a "-client" or "-server" process is treated, either by the JVM itself or OS itself – MadProgrammer Feb 03 '16 at 20:20
  • @MadProgrammer sure, but the Oracle JDK implements Java threads over native threads, and I don't believe that Linux will actually let a ready thread sit blocked for several seconds while there's an idle core for that whole time. Also, the problem manifests over a range of operating systems, which rules out some OS-specific quirk. – davmac Feb 03 '16 at 22:33
  • @MadProgrammer (there's also the matter of the 200% processor consumption, i.e. the process has two threads which are each actively scheduled to separate cores, not waiting. It really doesn't look to me like the EDT is not being scheduled - it looks like it's stuck in a tight loop - which is very strange). – davmac Feb 03 '16 at 22:39
  • @davmac As I understand it, Java `Thread`s a light wrappers around native OS threads, where the functionality is available on the OS – MadProgrammer Feb 03 '16 at 22:51
  • @MadProgrammer yes, that's what I meant by "implements Java threads over native threads". My point is that a native thread shouldn't sit idle (or worse, spinning) for seconds while there are idle processor cores available, on any reasonable OS. – davmac Feb 03 '16 at 22:55
  • I welcome @MadProgrammer's insight on this; I found this [article](http://www.cafeaulait.org/course/week11/32.html), cited above, helpful. I was intrigued to see the unyielding version of `t` also blocking the NetBeans profiler, as well as `jvisualvm`. – trashgod Feb 03 '16 at 23:46
  • @trashgod just bear in mind that a lot of the discussion about whether threads can/will pre-empt other threads (including the one you link) is relevant only for the situation where the threads are contending for a single processor (core). The Oracle JVM maps each Java thread to a separate native thread, and native threads can run on different processor cores - and should do so, if the cores are available. Neither thread needs to yield to nor be pre-empted by the other in this case. – davmac Feb 04 '16 at 00:29
  • I'd like to add another factor to discussion: the way the modality is implemented in the Swing. If you construct a blocking JOptionPane, the current EDT is being stopped ("parked") and a new one is created. If the blocking dialog is closed, the extra EDT thread is destroyed and the original one unparked. – Rekin Feb 04 '16 at 11:39
  • @Rekin: Good point; "A modal dialog only blocks user interaction," as suggested [here](http://stackoverflow.com/a/18728637/230513); I omitted the dialog as a distraction from the underlying problem. – trashgod Feb 04 '16 at 11:55
2

My observations:

  • Replace thread with swingworker:

    • No difference
  • Replace thread with swingworker and do some work inside the first for loop:

    • Got the expected results of the ui not freezing and the it was just smooth sailing from here on

With this code, the expected behaviour is observed:

public class MFrame extends JFrame {
    public static void main(String[] args) {
        new MFrame();
    }

    public MFrame() {
        JButton tryme = new JButton("Try me!");

        tryme.addActionListener((e) -> {
            SwingWorker<Void, Void> longProcess = new SwingWorker<Void, Void>() {
                private StringBuilder sb = new StringBuilder();

                @Override
                protected Void doInBackground() throws Exception {
                    int a = 4;
                    for (int i = 0; i < 100000; i++) {
                        for (int j = 0; j < 100000; j++) {
                            a *= (i + j);
                            a += 7;
                        }
                        sb.append(a); // <-- this seems to be the key
                    }
                    System.out.println("a = " + a);
                    return null;
                }

                @Override
                protected void done() {
                    try {
                        get();
                        System.out.println(sb.toString());
                    } catch (InterruptedException | ExecutionException e1) {
                        e1.printStackTrace();
                    }
                }
            };

            longProcess.execute();

            // Sleep to give the other thread a chance to get going.
            // (Included because it provokes the problem more reliably,
            // but not necessary; issue still occurs without sleep call).
            try {
                Thread.sleep(500);
            }
            catch (InterruptedException ie) {
                ie.printStackTrace();
            }

            // Now display a dialog
            SwingUtilities.invokeLater(() -> JOptionPane.showConfirmDialog(this, "You should see this immediately"));
        });

        getContentPane().add(tryme);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setVisible(true);
    }
}

The same observation is made by using OP's original code:

  • Do some other work inside the first for loop
    • Got expected results

Example

tryme.addActionListener((e) -> {

    Thread t = new Thread(() -> {
        StringBuilder sb = new StringBuilder();

        int a = 4;
        for (int i = 0; i < 100000; i++) {
            for (int j = 0; j < 100000; j++) {
                a *= (i + j);
                a += 7;
            }
            sb.append(a); // <-- again the magic seems to be on this line
        }
        System.out.println(sb.toString());
    });
    ...
});

I am running Ubuntu 14.04 on a semi powerful machine.

java version "1.8.0_72"
Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)

What do my observations mean?

Not much other than all is not lost and someone might have optimized the compiler a bit too much which makes it somehow block the UI thread. Honestly I'm not sure what it all means but I'm sure someone will figure it out

smac89
  • 39,374
  • 15
  • 132
  • 179
  • Interesting. Yes, the specific form of the nest loop structure seems to be what triggers the problem. I suspect doing anything that requires any kind of synchronisation (eg the memory allocation required by use of the StringBuilder) will prevent the problem from surfacing. – davmac Feb 04 '16 at 10:11
  • Unlike`StringBuffer`, `StringBuilder` is not synchronized. Good point about the structure; the optimizer may be interfering with preemption. – trashgod Feb 04 '16 at 12:00
  • @trashgod I know that `StringBuilder` methods are not synchronised. When I say "any kind of synchronisation" I do not mean just "Java-level synchronized blocks or methods" - I mean anything that requires synchronisation between threads at _some_ level, eg heap allocation, which I alluded to in my comment above. But your statement about preemption here is not correct. There are cores available, so there is no need for preemption, because the threads can (or at least should be able to) run independently on separate cores - and if they can't, the question "why not?" remains. – davmac Feb 04 '16 at 12:29
1
  • by default everything started from EDT (in this case inside the ActionListener) locked by Thread.sleep ended when all code is executed including Thread.sleep, with assumtion that you are lost all events incl. painting, during whole time cunsumed this code, all events are painted at the end and in one time

  • this code lost autoclose JOptionPane, never is painted to the screen (simulation of how to confortly Thread.sleep kills painting in Swing)

  • Swing GUI is unresponsible to mouse or key event, isn't possible to terminating this aplication, this is possible just from Runnable#Thread and SwingWorker, thats are designated to start new, another thread (Workers Thread), during anything inside Runnable#Thread and SwingWorker is task cancelable (or by using Runnable#Thread is there possible to pause, modify...)

  • this isn't about multithreading, nor about to share resourcer to another core(s), in Win10 all cores showing me, sharing the increment proportionally

output from (little bit modified) code (based on your SSCCE / MCVE)

run:
test started at - 16:41:13
Thread started at - 16:41:15
to test EDT before JOptionPane - true at 16:41:16
before JOptionPane at - 16:41:16
Thread ended at - 16:41:29
a = 1838603747
isEventDispatchThread()false
after JOptionPane at - 16:41:29
Thread started at - 16:41:34
to test EDT before JOptionPane - true at 16:41:34
before JOptionPane at - 16:41:34
Thread ended at - 16:41:47
a = 1838603747
isEventDispatchThread()false
after JOptionPane at - 16:41:47
BUILD SUCCESSFUL (total time: 38 seconds)

again autoclose JOptionPane never will be painted to the screen (tested win10-64b, i7, Java8), probably up to Java 1.6.022 everything will be painted and correctly (AFAIK the last fix to edt and from this time SwingWorker works without bugs)

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.Action;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class MFrame extends JFrame {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new MFrame();
        });
    }

    public MFrame() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        System.out.println("test started at - " + sdf.format(getCurrDate().getTime()));
        //http://stackoverflow.com/a/18107432/714968
        Action showOptionPane = new AbstractAction("show me pane!") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                createCloseTimer(3).start();
                System.out.println("before JOptionPane at - "
                        + sdf.format(getCurrDate().getTime()));
                JOptionPane.showMessageDialog((Component) e.getSource(), "nothing to do!");
            }

            private Timer createCloseTimer(int seconds) {
                ActionListener close = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Window[] windows = Window.getWindows();
                        for (Window window : windows) {
                            if (window instanceof JDialog) {
                                JDialog dialog = (JDialog) window;
                                if (dialog.getContentPane().getComponentCount() == 1
                                        && dialog.getContentPane().getComponent(0) instanceof JOptionPane) {
                                    dialog.dispose();
                                    System.out.println("after JOptionPane at - "
                                            + sdf.format(getCurrDate().getTime()));
                                }
                            }
                        }
                    }
                };
                Timer t = new Timer(seconds * 1000, close);
                t.setRepeats(false);
                return t;
            }
        };
        JButton tryme = new JButton("Try me!");
        tryme.addActionListener((e) -> {
            System.out.println("Thread started at - "
                    + sdf.format(getCurrDate().getTime()));
            Thread t = new Thread(() -> {
                int a = 4;
                for (int i = 0; i < 100000; i++) {
                    for (int j = 0; j < 100000; j++) {
                        a *= (i + j);
                        a += 7;
                    }
                }
                System.out.println("Thread ended at - "
                        + sdf.format(getCurrDate().getTime()));
                System.out.println("a = " + a);
                System.out.println("isEventDispatchThread()" + 
                        SwingUtilities.isEventDispatchThread());
            });
            t.start();
            // Sleep to give the other thread a chance to get going:
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
            // Now display a dialog
            System.out.println("to test EDT before JOptionPane - "
                    + SwingUtilities.isEventDispatchThread()
                    + " at " + sdf.format(getCurrDate().getTime()));
            showOptionPane.actionPerformed(e);
        });
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(tryme);
        pack();
        setLocation(150, 150);
        setVisible(true);
    }

    private Date getCurrDate() {
        java.util.Date date = new java.util.Date();
        return date;
    }
}

note have to test with Runnable#Thread and SwingWorker too

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I'm afraid that language is a barrier here, but I think you've possibly misunderstood the problem. The `Thread.sleep()` isn't essential to the problem, you can remove it from my MCVE and it will still exhibit an issue. – davmac Feb 02 '16 at 16:03
  • all painting in Swing is done (and in one moment, at the end) only when all code lines inside EDT are executed, then EDT flushed painting to the GPU, and whorse option is by using Thread.sleep, it can clears all paintings to the screen, nothing will be painted, you are in risk that you lost all events or part of them – mKorbel Feb 02 '16 at 16:11
  • I don't believe that using Thread.sleep actually causes paint events to be lost, but even if it does, as I have already said, the Thread.sleep can be removed from my example and it _still exhibits the issue_ (often in a slightly modified form) - the option pane dialog is not responsive. – davmac Feb 02 '16 at 16:14
  • in my case I lost JOPtionPane, see (better will be to test in your VM) time for `thread ended at` and `after JOptionPane at`, and isEventDispatchThread() must returns true, thats your problem, explanations EDT returns false after (true is a few seconds later) all events in EDT are fulshed, this is standard for all single threaded programing languages (incl. MsAccess) – mKorbel Feb 02 '16 at 16:18
  • the option pane dialog is not responsive. - Swing is single threaded, and reason for why SwingWorker is there, another test to runs long query by using JDBC, read large file (this is the same as your for_loop) - Swing GUI is unresponsive to all events, including terminations, daily there, tagged by eventdispatchthread – mKorbel Feb 02 '16 at 16:25
  • But I'm not blocking the EDT. The long calculation is done in a separate thread, which is _started_ from the EDT. The question is, why does the EDT stop processing while the other thread is running? – davmac Feb 02 '16 at 16:35
  • event queue must be empty (incl. shadowing, all event from APIs) and returns true – mKorbel Feb 02 '16 at 17:18
  • 1
    @mKorbel: Agree on `SwingWorker`; not sure how `JOptionPane` handles starvation. – trashgod Feb 02 '16 at 19:47
  • @trashgod there are two problems, code execution and EDT, plain Thread isn't workers thread in comparing with Runnable#Thread or SwingWorker, there is significant linear code execution, then EDT is (correctly) blocked, and second issue is that Thread.Sleep blocked JOptionPane (true is that sometimes on 1st. click showing me, but second and another are without JOptionPane), JOptionPane is designated to block code execution, then really nobody knows, maybe you are right, this is good point, I'm reduced to Win OS platform, and Java is significantly designated for this major Native OS, sorry ... – mKorbel Feb 03 '16 at 13:57
1

This is not a final answer, but it gets closer to understanding the problem.

I tried to minimize the code to remove potential pitfalls with sleep and actionPerformed and I believe I have done so while keeping the problem intact:

public class MFrame extends JFrame {

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> new MFrame());
    }

    public MFrame() {

        Thread t = new Thread(() -> {
            int a = 4;
            for (int i = 0; i < 50000; i++) {
                for (int j = 0; j < 50000; j++) {
                    a *= (i + j);
                    a += 7;
                }
            }
//          System.out.println("c" + a);
        });

        System.out.println("a");
//      pack();
        t.start();
//      pack();
        System.out.println("b");
    }
}

On Win7, i7 2670QM, JDK 1.8.0_25 I get the following results:

Only 2nd pack commented out:

a
b [pause]
c-1863004573

(expected since even without synchronization, printing b would be reached before printing c, unless maybe you are on some superduper processor that could do the calculation faster?)

Only 1st pack commented out:

a [pause]
c-1863004573
b

(not expected)

Can you confirm my results with/out the -client flag?

user1803551
  • 12,965
  • 5
  • 47
  • 74
  • there is one funny issue, JFrame must be visible, otherwise isn't possible to reproducing painting artefacts, nor to block an EDT, in this case an EDT dissapears after a few seconds (standard), returns false, again retuns true after the after last code line is executed(standard), this is only linear code execution with risk if EDT dissapears or not – mKorbel Feb 02 '16 at 17:14
  • to try to correctly redirect OPs for-loop to the workers thread e.g. by using Runnable#Thread, plain Thread and EDT is here milion times – mKorbel Feb 02 '16 at 17:16
  • I'm afraid I just get the same output in all cases - a,b, (pause), c, regardless of the presence or absence of either `pack` – davmac Feb 02 '16 at 17:19
  • (I assume the problem is triggered by some specific timing. It behaves slightly differently on different machines; this I've established already. I think messing around with the form of the example isn't going to help much, to be honest). – davmac Feb 02 '16 at 17:26
  • @davmac If you remove the print line in the thread in your example, does it make no difference? – user1803551 Feb 02 '16 at 22:49
  • @user1803551 actually it does make a difference and suppresses the problem. However, removing the print statement potentially allows the JIT to optimise away the entire loop, which does appear to be what happens because I see no CPU usage. If I replace the print statement with an assignment to a static variable (`m = a;`) then the problem returns. – davmac Feb 03 '16 at 11:03
  • @davmac Ah, I was wrong then. Do you get this issue only with the EDT is involved? – user1803551 Feb 03 '16 at 16:05
  • @user1803551 yes, so far I've only been able to reproduce when the EDT is involved. – davmac Feb 03 '16 at 16:34
1

This seems to be an issue. Below are the observation Event Dispatcher Thread delays the processing, Should have responded immediately:

  1. Execute sample program
  2. Click "Try me" button
  3. Click any button (yes/no/cancel) to close the resulting dialog

On Windows

Long delay observe between step 2 and step 3.

Step 3 -> closes the dialog immediately.

On Linux

Step 2 to step 3 - no delay.

Step 3 -> long delay to close the dialog .

user1803551
  • 12,965
  • 5
  • 47
  • 74
Fairoz
  • 1,616
  • 13
  • 16