appcontext.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 761 行 · 第 1/2 页
JAVA
761 行
* frames[i].dispose(); // Dispose of all top-level Frames * } * synchronized(notificationLock) { * notificationLock.notifyAll(); // Notify caller that we're done * } * } }; * synchronized(notificationLock) { * SunToolkit.postEvent(this, * new InvocationEvent(Toolkit.getDefaultToolkit(), runnable)); * try { * notificationLock.wait(DISPOSAL_TIMEOUT); * } catch (InterruptedException e) { } * } */ // Next, we post another InvocationEvent to the end of the // EventQueue. When it's executed, we know we've executed all // events in the queue. Runnable runnable = new Runnable() { public void run() { synchronized(notificationLock) { notificationLock.notifyAll(); // Notify caller that we're done } } }; synchronized(notificationLock) { SunToolkit.postEvent(this, new InvocationEvent(Toolkit.getDefaultToolkit(), runnable)); try { notificationLock.wait(DISPOSAL_TIMEOUT); } catch (InterruptedException e) { } } // Next, we interrupt all Threads in the ThreadGroup this.threadGroup.interrupt(); // Note, the EventDispatchThread we've interrupted may dump an // InterruptedException to the console here. This needs to be // fixed in the EventDispatchThread, not here. // Next, we sleep 10ms at a time, waiting for all of the active // Threads in the ThreadGroup to exit. long startTime = System.currentTimeMillis(); long endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT; while ((this.threadGroup.activeCount() > 0) && (System.currentTimeMillis() < endTime)) { try { Thread.sleep(10); } catch (InterruptedException e) { } } // Then, we stop any remaining Threads // this.threadGroup.stop(); // Next, we sleep 10ms at a time, waiting for all of the active // Threads in the ThreadGroup to die. startTime = System.currentTimeMillis(); endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT; while ((this.threadGroup.activeCount() > 0) && (System.currentTimeMillis() < endTime)) { try { Thread.sleep(10); } catch (InterruptedException e) { } } // Next, we remove this and all subThreadGroups from threadGroup2appContext int numSubGroups = this.threadGroup.activeGroupCount(); if (numSubGroups > 0) { ThreadGroup [] subGroups = new ThreadGroup[numSubGroups]; numSubGroups = this.threadGroup.enumerate(subGroups); for (int subGroup = 0; subGroup < numSubGroups; subGroup++) { threadGroup2appContext.remove(subGroups[subGroup]); } } threadGroup2appContext.remove(this.threadGroup); MostRecentThreadAppContext recent = mostRecentThreadAppContext; if ((recent != null) && (recent.appContext == this)) mostRecentThreadAppContext = null; // If the "most recent" points to this, clear it for GC // Finally, we destroy the ThreadGroup entirely. try { this.threadGroup.destroy(); } catch (IllegalThreadStateException e) { // Fired if not all the Threads died, ignore it and proceed } synchronized (table) { this.table.clear(); // Clear out the Hashtable to ease garbage collection } numAppContexts--; mostRecentKeyValue = null; }/* There is no AWTAutoShutdown in pbp right now** static final class PostShutdownEventRunnable implements Runnable {* private final AppContext appContext;** public PostShutdownEventRunnable(AppContext ac) {* appContext = ac;* }* * public void run() {* final EventQueue eq = (EventQueue)appContext.get(EVENT_QUEUE_KEY);* if (eq != null) {* eq.postEvent(AWTAutoShutdown.getShutdownEvent());* }* }* }*** static final class CreateThreadAction implements PrivilegedAction {* private final AppContext appContext;* private final Runnable runnable;** public CreateThreadAction(AppContext ac, Runnable r) {* appContext = ac;* runnable = r;* }* * public Object run() {* Thread t = new Thread(appContext.getThreadGroup(), runnable);* t.setContextClassLoader(appContext.getContextClassLoader());* t.setPriority(Thread.NORM_PRIORITY + 1);* t.setDaemon(true);* return t;* }* }*** static void stopEventDispatchThreads() {** // Use clone, so that concurrent modification of threadGroup2appContext ** // won't mess up the enumeration.** Hashtable clone = (Hashtable)threadGroup2appContext.clone();* Enumeration allAppContexts = clone.elements();** while (allAppContexts.hasMoreElements()) {* AppContext appContext = (AppContext)allAppContexts.nextElement();** Runnable r = new PostShutdownEventRunnable(appContext);* // For security reasons EventQueue.postEvent should only be called* // on a thread that belongs to the corresponding thread group.* if (appContext != AppContext.getAppContext()) {* // Create a thread that belongs to the thread group associated* // with the AppContext and invokes EventQueue.postEvent.* PrivilegedAction action = new CreateThreadAction(appContext, r);* Thread thread = (Thread)AccessController.doPrivileged(action);* thread.start();* } else {* r.run();* }* }* }*/ private MostRecentKeyValue mostRecentKeyValue = null; /** * Returns the value to which the specified key is mapped in this context. * * @param key a key in the AppContext. * @return the value to which the key is mapped in this AppContext; * <code>null</code> if the key is not mapped to any value. * @see #put(Object, Object) * @since JDK1.2 */ public Object get(Object key) { // Note: this most recent key/value caching is thread-hot. // A simple test using SwingSet found that 72% of lookups // were matched using the most recent key/value. By instantiating // a simple MostRecentKeyValue object on cache misses, the // cache hits can be processed without synchronization. MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) { return recent.value; } /* * The most recent reference should be updated inside a synchronized * block to avoid a race when put() and get() are executed in * parallel on different threads. */ synchronized (table) { Object value = table.get(key); mostRecentKeyValue = new MostRecentKeyValue(key, value); return value; } } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this AppContext. Neither the key nor the * value can be <code>null</code>. * <p> * The value can be retrieved by calling the <code>get</code> method * with a key that is equal to the original key. * * @param key the AppContext key. * @param value the value. * @return the previous value of the specified key in this * AppContext, or <code>null</code> if it did not have one. * @exception NullPointerException if the key or value is * <code>null</code>. * @see #get(Object) * @since JDK1.2 */ public Object put(Object key, Object value) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = value; return table.put(key, value); } } /** * Removes the key (and its corresponding value) from this * AppContext. This method does nothing if the key is not in the * AppContext. * * @param key the key that needs to be removed. * @return the value to which the key had been mapped in this AppContext, * or <code>null</code> if the key did not have a mapping. * @since JDK1.2 */ public Object remove(Object key) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = null; return table.remove(key); } } /** * Returns the root ThreadGroup for all Threads contained within * this AppContext. * @since JDK1.2 */ public ThreadGroup getThreadGroup() { return threadGroup; } /** * Returns the context ClassLoader that was used to create this * AppContext. * * @see java.lang.Thread#getContextClassLoader */ public ClassLoader getContextClassLoader() { return contextClassLoader; } /** * Returns a string representation of this AppContext. * @since JDK1.2 */ public String toString() { return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]"; } /** * Returns an array of all the property change listeners * registered on this component. * * @return all of this component's <code>PropertyChangeListener</code>s * or an empty array if no property change * listeners are currently registered * * @see #addPropertyChangeListener * @see #removePropertyChangeListener * @see #getPropertyChangeListeners(java.lang.String) * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners * @since 1.4 * public synchronized PropertyChangeListener[] getPropertyChangeListeners() { * if (changeSupport == null) { * return new PropertyChangeListener[0]; * } * return changeSupport.getPropertyChangeListeners(); * } */ /** * Adds a PropertyChangeListener to the listener list for a specific * property. The specified property may be one of the following: * <ul> * <li>if this AppContext is disposed ("disposed")</li> * </ul> * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName one of the property names listed above * @param listener the PropertyChangeListener to be added * * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * public synchronized void addPropertyChangeListener( * String propertyName, * PropertyChangeListener listener) {* if (listener == null) {* return;* }* if (changeSupport == null) {* changeSupport = new PropertyChangeSupport(this);* }* changeSupport.addPropertyChangeListener(propertyName, listener); *} */ /** * Removes a PropertyChangeListener from the listener list for a specific * property. This method should be used to remove PropertyChangeListeners * that were registered for a specific bound property. * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName a valid property name * @param listener the PropertyChangeListener to be removed * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) *public synchronized void removePropertyChangeListener( * String propertyName, * PropertyChangeListener listener) { * if (listener == null || changeSupport == null) { * return; * } * changeSupport.removePropertyChangeListener(propertyName, listener); *} */ /** * Returns an array of all the listeners which have been associated * with the named property. * * @return all of the <code>PropertyChangeListeners</code> associated with * the named property or an empty array if no listeners have * been added * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners * @since 1.4 *public synchronized PropertyChangeListener[] getPropertyChangeListeners( * String propertyName) { * if (changeSupport == null) { * return new PropertyChangeListener[0]; * } * return changeSupport.getPropertyChangeListeners(propertyName); *} */}final class MostRecentThreadAppContext { final Thread thread; final AppContext appContext; MostRecentThreadAppContext(Thread key, AppContext value) { thread = key; appContext = value; }}final class MostRecentKeyValue { final Object key; Object value; MostRecentKeyValue(Object k, Object v) { key = k; value = v; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?