In swing programs, you can often see the following code:
Swingutilities.invokelater (new Runnable () { @Override publicvoid Run () { textfield1.settext ("element changed!") ); Textfield1.setforeground (color.red); } });
Why use Swingutilities.invokelater instead of calling it directly? Because most swingapi are non-thread-safe, which means they cannot be called anywhere, it should only be called in EDT. Swing's line Shuo is guaranteed by the event queue and EDT.
The eventqueue distribution mechanism is managed by a single thread called the event Dispatch thread (EDT). Like many other desktop APIs, swing executes the GUI request into an event queue.
With EDT, the non-thread-safe swing library avoids the problem of concurrent access.
Background Concept
To understand EDT, you need to know some background concepts first:
Synchronous vs. Asynchronous:
synchronization is when a program starts processing an event after initiating a request, waits for the result of processing, or waits for the request to complete before the program is blocked until the request is completed.
asynchronous is returned immediately after the current program initiates the request, the current program does not immediately process the event and waits for the result of processing, and the request is processed at a later time.
Serial vs. Parallel:
serial refers to a number of orders to process the execution of requests, processing a second processing the next;
parallelism can be understood as concurrency, which is to handle multiple requests at the same time (in fact, we can only understand that, especially if the number of CPUs is less than the number of threads, the true meaning of concurrency is nonexistent, and each thread executes alternately intermittently).
Demonstrates the mechanism of serial and parallel. It can be said that before the introduction of multithreading, for the same process or program to do is a serial operation.
Serial:
Parallel:
Producer/consumer model:
Imagine a scene in which a conveyor belt, one or more entrances, constantly produces the goods to be processed, and this constantly produces goods called producers; the end of a conveyor belt is one or more workers in the processing of goods, called consumers. Sometimes, because there is not enough cargo on the conveyor belt to make a worker temporarily idle, and sometimes because some of the goods need to be processed for a longer period of time on the conveyor belt to be processed goods piled up.
If you implement a simple producer consumer model in Java, it is easy to use the thread's wait/notification mechanism.
Public classSyncqueue {PrivateList buffer =NewArrayList (); //Consumer Public synchronizedObject Pop () {object E; while(buffer.size () = = 0) { Try{wait (); } Catch(interruptedexception E1) {//Ignore it}} e= Buffer.remove (0); returne; } //Production Public synchronized voidpush (Object e) {notifyall (); Buffer.add (e); } }
Event queue:
In the computer data structure, the queue is a special data structure. One, it is linear, the other, the element is first-out, that is, the elements into the queue must be entered from the end, the first queued elements are executed first, after the queued elements wait for the previous elements to execute after the team to execute, the processing of the queue is executed one after the next execution.
Queue and thread safety are two different concepts, and if you want to add thread-safe features to the queue, you only need to follow the above producer/consumer plus thread wait/notification .
Threads in the Swing program
A swing program typically has the following three types of threads:
- Initializing thread (Initial thread)
- UI Event Dispatch thread (EDT)
- Task threads (Worker thread)
Initializing Threads: Each program must have a main method, which is the entry for the program. The method runs on the initialization or startup thread. Initializes a thread to read the program parameters and initializes some of the objects. In many swing programs, the main purpose of the thread is to start the program's graphical user interface (GUI).
The point at which the UI is created, the point at which the program starts handing control over to the UI。 Once the GUI is started, the initialization of the thread is over for most event-driven desktop programs.
EDT: The swing program has only one EDT, which is responsible for drawing and updating the GUI components and responding to user interaction by invoking the program's event handlers. All event handling is done on the EDT, and the interaction of the program with the UI component and its basic data model is only allowed on the EDT, and all tasks running on the EDT should be completed as soon as possible so that the UI responds to user input in a timely manner.
Swing should be aware when programming:
- Accessing the UI component and its event handlers from other threads can cause interface updates and drawing errors. --The component must be refreshed through EDT
- Executing a time-consuming task on the EDT causes the program to lose its response, which causes the GUI event to be blocked from being processed in the queue. --Cannot perform other time-consuming operations in the EDT
- You should use a separate task thread to perform time-consuming calculations or input-output-intensive tasks, such as communicating with a database, accessing Web site resources, and reading and writing tree data. --time-consuming operations should be placed in a separate task thread, initiated via SwingWorker
In summary, any interference or delay in UI event processing should only occur in the standalone task thread; In the initialization thread (that is, the frame! cannot be created directly in the Main method) The Invokelater method initialization program interface should be used in the initialization thread, or the interaction between the Chengtong swing component or its default data model is a non-threading security operation.
the SwingWorker class helps you manage the interaction between task threads and EDT, although SwingWorker does not solve all of the problems encountered in concurrent threads, it does help separate Swingedt and task threads, making them accountability: for EDT, it is the drawing and updating interface and responding to user input; For a task thread, say, is the execution of time-consuming tasks and I/O intensive operations that are not directly related to the interface.
Swing Event Distribution thread
Swing's event queue is similar to the above event queue (the rationale is similar, but the swing internal implementation will do some optimizations), saying it is a single-threaded graphics toolkit that refers to only a single consumer, often said event distribution thread (EDT), generally speaking, Unless your application stops, the EDT will never stop hovering between processing requests and waiting requests.
is the implementation mechanism of the Swing event queue:
Obviously, if it takes a long time to process a certain item, the subsequent goods have to wait.
There are two very prominent features for a single-threaded event queue:
- Converts a synchronization operation to an asynchronous operation.
- Converts parallel processing to serial sequential processing.
EDT to handle all GUI operations, it is a distinct and very busy job. That means you have to remember two principles:
- The responsibilities are clear, and any GUI requests should be called in the EDT.
- There are a lot of GUI requests to be processed, including window movement, component Auto-redraw, refresh, and it is busy, so any GUI-agnostic processing is not handled by EDT, especially the time-consuming operation of I/O.
The above said swing is not a "security thread" API, why design it? Looking back, you'll understand that swing's thread safety is not guaranteed by its own component's API, although the Repaint method is, but most swingapi are non-thread-safe, meaning they cannot be called anywhere, it should only be called in EDT. Swing's line Shuo is guaranteed by the event queue and EDT.
Invokelater and Invokeandwait
Since swing itself is not thread-safe, if you access and modify GUI components on other threads, you have to use Swingutilities. Invokeandwait (runnable), swingutilities. Invokelater (runnable). This means that concurrent calls to non-EDT need to be inserted into the queue by Invokelater () and invokeandwait () to wait for the EDT to execute .
- The Invokelater (runnable) method is asynchronous , it returns immediately, and when the request is executed is not determined, so the named Invokelater is called later.
- The Invokeandwait (runnable) method is synchronous , and the end of the call will immediately block the current thread (the thread that called invokeandwait) until the EDT finishes processing the request . Invokeandwait general application is to obtain data for swing components.
Invokeandwait has a very important guideline: it cannot be called in EDT , otherwise the program throws an error and the request is not executed. See Source:
Public Static voidinvokeandwait (Runnable Runnable)throwsinterruptedexception, InvocationTargetException {//cannot call invokeandwait in EDT if(Eventqueue.isdispatchthread ()) {Throw NewError ("Cannot call Invokeandwait from the event dispatcher thread"); } classAwtinvocationlock {} Object lock=NewAwtinvocationlock (); Invocationevent Event=Newinvocationevent (Toolkit.getdefaulttoolkit (), runnable, lock,true); synchronized(lock) {//add into event queuetoolkit.geteventqueue (). postevent (event); //Block Current threadlock.wait (); } throwable eventthrowable=event.getthrowable (); if(Eventthrowable! =NULL) { Throw Newinvocationtargetexception (eventthrowable); } }
If Invokeandwait is called in EDT, the request is first pressed into the queue, then EDT is blocked, waiting for the request to end to notify it to continue running.
In fact, the request will never be executed, because it waits for the queue to be dispatched to the EDT to execute it, which is a deadlock: EDT waits for the request to execute first, and the request waits for the EDT to dispatch the queue. Waiting for each other to release the lock is one of the four types of conditions that cause a deadlock. Swing has deliberately avoided this kind of situation.
Original address: Jump
"Go" Swing with EDT thread