public static void executeOnSwingWithoutBlocking(Runnable runnable) {

		AtomicBoolean didRun = new AtomicBoolean();
		(new Thread() {
			@Override
			public void run() {
				didRun.set(true);
				runSwing(runnable);
			}
		}).start();

		// we can make this call, since any potential modal dialogs are not blocking in the Swing
		// thread, but in the new event queue created by the modal dialog (this is how repainting
		// still works when a modal dialog is shown)
		waitForSwing();

		waitForCondition(() -> didRun.get());

		// pause a bit to let the swing thread process
		sleep(DEFAULT_WAIT_DELAY);

		// make sure any pending Swing events have been processed
		waitForSwing();
	}
Launches the runnable on a new thread so as to not block the calling
thread. This is very useful for performing actions on the Swing thread
that show modal dialogs, which would otherwise block the calling thread,
such as a testing thread.

@param runnable The runnable that will be executed in a new Thread that
           will place the runnable on the Swing thread.
Ghidra/Framework/Gui/src/main/java/generic/test/AbstractGuiTest.java