Swing thread final discussion - use asynchronous model

xiaoxiao2021-03-06  82

Introduction and review Before Drilling Tree, Table and Asynchronous Models, I first reviewed Single-Thread Rule and tested its meaning. Swing's single-threading rule is that Swing components can only be accessed by one thread at a moment. This rule is valid for gets and sets, and "a thread" usually refers to event distribution threads. SLR rules apply to the UI component is very commensuer, because the UI component is often used in single-threaded manner, and most acts are initiated by the user. Components to build threads are difficult and long-tedious: if it is avoided, it is preferred. But except for its benefits, single thread rules have more meaning. All events of SWING components are sent and received in event-dispatch threads, in addition to this only complied with single threaded rules. For example, Property-Change Events should be sent in the event dispatching thread, and model change events should be received in the event dispatching. For model-based components such as JTABLE and JTREE, single thread rules mean that they can only access the model itself in the event dispatching. For this reason, the method in the model must be implemented soon and must not block, otherwise the entire user interface will be slow. But imagine that you have a JTREE with Treemodel to access a remote server? You will find that when the server is unavailable or too busy, your TreeModel's call will block and make the entire user interface frozen. What can you do to improve the responsiveness of the interface? Again, have a JTABLE with TABLEMODEL to manage a device on the network? You will find that when the managed equipment is busy or the network is crowded, the interface becomes slow. what should you do? These difficulties are in summoning threads. When the demand has emerged, we still have several ways to use threads in Swing, although there is a single threaded rule. This article shows two ways to use threads to access slow, remote, or other asynchronous models and display how to use in JTREE and JTABLE components. (Not only the models of the event sending threads are called "asynchronous" models.) ------------------------------- ----------------------------------------------

Dynamic tree

Suppose you have a JTree with TreeModel to access the remote server, but the server is slow or unreliable, what should you do? DynamICTree demonstrates how to dynamically expand the JTree node using the background thread. Figure 1 is a DynamiCTree being processed in the processing node. figure 1

Split model (split-model) design

DynamicTree is based on a split model design (Split-Model Design). In this design, the real model is an asynchronous model that may be slow or unreliable. The JTree model uses a standard synchronization model to maintain a true model of Snapshot. (Asynchronous models may be in remote servers, I usually call remote models for this reason, and I refer to the model of Swing components as local models.) Use local models to image or cache remote models help to provide one at all times Swing components of all reliable, high response capabilities. But a shortcoming of this method is also the necessary cost is that the model data has to be repeated. Another problem is that the two models are not always synchronized, and they have to be coordinated with each other.

Update when expanding: Dynamic browsing

One coordination method between the model is to update the local model only when data is required, not before this. This technique is useful when the remote model is slow or large, but this technical requirement model is basically static. DynamicTree uses this method to browse a slow static tree model. DynamicTree is a unniffered root node, and there is an Expansion Listener waiting for user input to expand the node. When the node is expanded, expand the auditor to launch a SwingWorker thread. This Worker's construct () method accesses the remote model and returns a new child node. Then Worker's finished () method will execute in the event dispatch, add the child node to the local model. For simplicity, only one worker is allowed at the same time. If any node is folded, any Worker currently will be interrupted. (The program does not check if the folded node is the ancestors of the Node that worked in Worker.)

Figure 2 shows the process of starting the node. The execution process starts and ends in the event distribution thread on the left. SwingWorker starts in the Worker thread on the right side of the figure. The solid arrow is a method call, the dotted arrow is returned, and the half arrow is an asynchronous request. Figure 2 DynamICTree Performs the remainder of the sequence map This section discusses the class structure and implementation. You can also skip the following remote model demo. The following "Download" section explains how to download and run the presentation.

achieve

Figure 3 is a schematic class structure diagram. Figure 3 DynamAmICtree's local model is a defaulttreemodel with the DefaultMutableTreenode node. The node must be variable so that the child node can be dynamically added. The UserObject domain of variable nodes can be used to point to the remote model.

TreenodeFactory

The remote model implements the TreenodeFactory interface: public interface TreenodeFactory {defaultmutableTreenode [] CreateChildren (Object userObject) throws exception;} CreateChildren () is called in the Worker thread. Similar to most asynchronous and remote methods, it will throw an exception (generally a remoteexception or interruptedException). The UserObject parameter is a recently expanded node to refer to a link to the remote model. One returns an array including all child nodes is more efficient than alone, and can avoid the face of the face failure. At initialization, each child node is set to be set by the allowschildren property and a link to the remote model. (If the remote node is the leaves node, the AllowsChildren property is set to false; otherwise, AllowSchildren is set to True to indicate that the node can be expanded.) DefaultTreenodeFactory is an Adapter (please refer to GOF "Design Patterns"). It uses any TreeModel to connect to the TreenodeFactory interface. The default tree model is used in the demo program. Some comments in the main method demonstrate how to install a FileSystemNodeFactory. SlowtreenodeFactory is a packaging class that demonstrates; it is inserted into a random delay in run.

future job

I have tried to keep DynamicTree simple. There is no other content in the node in addition to the node. In the case where the content is required in the node, if you can load the content asynchronously, it will be better, such as you may use a tree selection listener to initialize the loading process. The remote performance presentation program in the next section will be more practical. -------------------------------------------------- ---------------------------- Remote Table

Suppose you have a JTable with TableModel to manage a remote device, but the interface is slow when the device is busy, what should you do? The following remote spending programs use the background thread and asynchronous callbacks to display or modify a remote table model. Figure 4 is a remote table editor being sent to the server a new value. Unprocessed cells remain yellow before the update is complete. Figure 4

RemoteTable bean

Remote performances are implemented with RMI, which consists of one server and two clients (an editor and a viewer). The viewer is actually a editor that is forbidden to edit the function. The client uses a RemoteTable component bean, and RemoteTable is a subclass of JTable designed to work with the remote table model. The editor shown in Figure 4 is constructed of a RemoteTable component, a status tag, a simple activity meter (lower right corner), and some code for locating the server.

Update when notification

DynamICTree updates its local model only when data is required, in this regard, the RemoteTable component gets all the data at the beginning and listens to changes. The technique based on notification-based can work with the dynamic model and works well in the model. Modify driver notification for cells. When the user completes the editing of the cell, RemoteTable labeled the edited cells as unprocessed (yellow highlighting) and arranges a SwingWorker task. The WOKER's construct () method sends a new value to the remote model. When the remote model receives a new value, it notifies the listener. The unique function of the Worker's finished () method is to confirm that the task has been completed; after the notification from the remote model is accepted and processed, the yellow unprocessed cells change back to the normal cell.

Task queue

RemoteTable scheders its SwingWorker task with a Queuedexecutor, QueuedExecutor executes all tasks in a single thread. (Queuedexecutor is part of the DOUG LEA's Util.Concurrent package, see the "Reference" section later.) The remote model notifies its listener with the RMI callback operation. In order to support visual feedback, RemoteTable sends a Task event to the registered Task listener. When the task enters schedule, the taskstarted () of the listener is called, and taskended () is called when the task is completed. The client demo program uses these events to start or stop a small image and update the status.

Execution order

Figure 5 shows a cell update process. The start and end of the execution process is located on the left event distribution thread. The SwingWorker task is executed in the thread of the EXECUTOR on the right. The execution process of the Worker's finished () method is not expressed. Figure 5 RemoteTable execution sequence diagram

simplify

Simple, the remote model does not protect the editing of mutual conflict. So there can be one editor at the same time. (Concurrent editing can be implemented with the method of adding request ID (Request IDs).) Another simplified decision is that the client and server must negotiate with the column structure of the table in advance. In other words, the server-based client provides row data, and the client must already know what the table they have to handle. The client used the client to pre-define the names and classes of each column in advance to determine which cell can be edited. (In the demo program, the first two columns are not editable.) The remainder of this section describes the class structure and implementation. If you don't want to know the revised SwingWorker used in this demo, you can jump over. "Download" section explains how to download and run this demo. achieve

Figure 6 is a schematic class configuration diagram. Figure 6 RemoteTable Various remote models implements the RemoteTableModel interface, which is similar to AbstractTableModel, except that all of it will throw an exception. To launch a client, the remote table model sends a full update event to the client's registered listener. RemoteTableModeLadapter comes with any TableModel to a RemoteTableModel. The table model in the demo procedure is taken from the Java Tutorial, but some delays are inserted to simulate the actual situation. The remote table model event contains the value of the updated cell. RemoteTable components use a defaultRemoteTableModelliStener to accept callbacks from the remote model. This listener updates the local model in the event dispatching process. Because the remote model may notify inform or delete some rows, the listener requires the local model to support insert and delete operations, and DefaultTableModel satisfies this requirement. -------------------------------------------------- -----------------------------

SwingWorker Revision

The demo program performs a fee when it costs in the background, and then updates the UI. The SwingWorker used by this demonstration is based on the SwingWorker class proposed in the SwingWorker thread, but re-implements it to correct a rapid condition, add timeout support, and improve the exception handling. This new implementation is also based on the Futureresult class of the Doug LEA's Util.Concurrent package (see "Reference" section). Since the work done by Futureresult, the implementation of the SwingWorker class is simple and flexible. The remaining parts of this section describe the details of the implementation in more detail, please continue to look down or jump directly to the back download source.

Runnable Futureresult

Futureresult, as its name is implicit, it is used to maintain a result of a move. It is designed to use with a Callable, Callable is a RunNable action that will return results: public interface callable {Object call () throws exception;} New SwingWorker is a runnable Futureresult. At runtime, it sets the result into a return value of construct () and then calls the finished () method in the event dispatch. (Note: SwingWorker is an abstract class; you want to type it and implement construct () and finished ().) The following code from SwingWorker Run () method: Callable function = new callable () {public Object call () THROWS EXCEPTION {RETURN Construct ();}}; runnable Dofinished = new runnable () {public void Run () {finish ();}}; setter (function) .Run (); swingutilities.invokelater (Dofinished); first Segment converts construct () into a Callable action, the second paragraph converts Finished () into the Dofinished as a runnable. Then setter is run, and Dofinished is called. Setter (Function)

The material that is missing is setter (function). It creates a engraved runnable. At runtime, this runnable calls the Function specified by the parameter, and then returns the result settings. The following is a code from Futureresult: Public runnable setter (Final Callable Function) {Return New Runnable () {PUBLIC VOID RUN () {Try {set (Function.Call ());} catch (throwable ex) {setException (ex) Pay attention to the protection of the try-catch block. If construct () throws anything (Exception, Error, etc.), will be captured and recorded.

Don't grab: first construct, then start

Call Start () to launch the worker thread. This is an important difference between the revised SwingWorker and the original version. In the original version, the SwingWorker () constructor automatically starts threads, which brings a risk of competition for threads and sub-constructor: When the SwingWorker () constructor has launched threads, while the subclass constructor is also not complete. Method is to construct SwingWorker first, then call START (). By the way, RemoteTable does not call Start (). Correctly, SwingWorker is executed as a runnable by Queuedexecutor.

Overtime support

The new SwingWorker supports timeout, which is implemented by overriding the gettimeout () method has returned a non-zero value. When the timeout time, the Worker thread will be interrupted. If you want to view an example of using the timeout, see how the comment version gettimeout () method and DynamICTree handle TimeOutException. The timeout function is implemented with timedcallable, which uses Futureresult's TimEt () method. Enhanced abnormal treatment

Anything thrown by the construct () method will be recorded. In addition to death cycles and deadlocks, new abnormalities ensure that SwingWorker is "ready". That is to say, it either gives a correct result or gives an exception. The following GET () method is used to take the result. This method inherits from the Futureresult: Public Object Get () THROWS INVOCATIONTARGETEXCEPTION, INTERRUPTEDEXCEPTION If construct () throws an Exception, the get () method will throw an InvocationTargeTexception. To get the construct () method actually throwing an exception, you can call getTargeTException (). If the thread of the result is interrupted during the wait result, the GET () method will throw InterruptedException - but this situation is rare for SwingWorker, because the thread of the result is usually the event distribution thread, and in Finished () The result is always ready before calling.

More call tools

SwingWorker's implementation is in the Jozart.swingutils package. In the same package, you can find the InvokeUtils class, which also provides several invokexxxx () methods. The background thread can use these methods to get values ​​and user inputs in the event dispatch thread, and return the results to the background thread. -------------------------------------------------- -----------------------------

download

The source code of all demonstrations, and compiled class files and resources, including in this zip file:

Threads3 Demos.zip

The threads3_demos.zip file includes the following: • Jozart / o DynamICTree / - DynamICTree demo. O RemoteTable / - RemoteTable bean source. O RemoteTableDemo / - RemoteTable demos. O Swingutils / - SwingWorker. • EDU / - Util.concurrent package (including the used class). • Java.Policy - The RMI Security Policy file (Security Policy). • RemoteTable.jar - RemoteTable Bean Note: Class from Util.Concurrent is selected from V1.2.3. Only the class used in the demo program is included. Note: Java 2 is required to run these presentations. (Util.Concurrent package has a number of collections.) Run demo, first decompress Threads3_Demos.zip to an empty folder, be careful not to change the name of the folder inside. Then change to the folder you extract the file to the file.

Run DynamicTree

Run the DynamAmICTree as an Applet:> AppletViewer Jozart / DynamicTree / DynamicTree.html Run the DynamicTree as Application:> Java Jozart.DynamicTree.dyNamict Run RemoteTableDemo

Remote table servers and clients are designed with RMIs to run separately. But RMI may be difficult to set. RMI requires a RMI Registry, an HTTP server and a security policy file. Fortunately, another demo procedure is not so troublesome, I will explain how to run it. RemoteTableDemo packed an editor, a viewer and a server. Run RemoteTableDemo as an Applet:> AppletViewer Jozart / RemoteTableDemo / RemoteTableDemo.html Run REMOTETABLEDEMO as an Application:> Java Jozart.RemoteTablesDemo.remoteTableDemo

Run server and client separately

To run the servers and clients, you need to perform the following steps: 1. Determine RMIREGISTRY to run:> Start rmiregistry2. Make sure there is an HTTP server being running:> start httpd3. For the directory of the demo program. > Cd threads34 start the server and client:.> Java -Djava.security.policy = java.policy -Djava.rmi.server.codebase = http: // host / threads3 / jozart.remotetabledemo.RemoteTableServer> java -Djava.security .policy = java.policy -Djava.rmi.server.codebase = http: // host / threads3 / jozart.remotetabledemo.RemoteTableEditor> java -Djava.security.policy = java.policy -Djava.rmi.server.codebase = http : // host / threads3 / jozart.remotableDemo.remoteTableViewer You need to set your correct host name in the CodeBase settings. You should also check that java.polic does not give too much permissions. For more information on RMI, see The Java Tutorial (see "Reference" section). -------------------------------------------------- ----------------------------

in conclusion

转载请注明原文地址:https://www.9cbs.com/read-122202.html

New Post(0)