All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zkoss.zkex.zul.impl.OperationThread Maven / Gradle / Ivy

There is a newer version: 3.6.3
Show newest version
/* OperationThread.java

 {{IS_NOTE
 Purpose:
 
 Description:
 
 History:
 Sep 29, 2007 9:21:36 AM     2007, Created by Dennis.Chen
 }}IS_NOTE

 Copyright (C) 2007 Potix Corporation. All Rights Reserved.

 {{IS_RIGHT
 This program is distributed under GPL Version 2.0 in the hope that
 it will be useful, but WITHOUT ANY WARRANTY.
 }}IS_RIGHT
 */
package org.zkoss.zkex.zul.impl;

import org.zkoss.lang.D;
import org.zkoss.util.logging.Log;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.DesktopUnavailableException;
import org.zkoss.zk.ui.Executions;

/**
 * This class is for model sharer developer only, you rarely need to use this class.
* * OperationThread has only one instance in each desktop, it store it-self in the desktop by setAttribute. * It create and monitor the {@link OperationQueue}, if there are any operation in queue, it will consume it.
* * @author Dennis.Chen * @since 3.0.0 */ public class OperationThread extends Thread { private static final String DESKTOP_KEY = "zkex:opthread"; private boolean _running = true; private OperationQueue _queue; private Desktop _desktop; private long _activateTimeout = 10000; private long _waitTimeout = 10000; private int _maxFailCount = 4; private static final Log log = Log.lookup(OperationThread.class); /* package */OperationThread(Desktop desktop) { _desktop = desktop; _queue = new OperationQueue(); this.setName("OPThread-" + desktop.getId()); } /* package */OperationQueue getQueue() { return _queue; } /** * Get the {@link OperationQueue} of {@linkplain OperationThread}, * It is check is there any {@linkplain OperationThread} exist in desktop. * If no, create one ,start it and store in desktop, then return thread's operation queue. * If yes, return operation queue directly. * * There is only one {@linkplain OperationThread} in each desktop. * @param desktop the associated desktop * @return a queue which associate to desktop */ public static OperationQueue getQueue(Desktop desktop) { if (desktop == null) throw new NullPointerException("desktop is null"); synchronized(desktop) { if (!desktop.isAlive()) { throw new IllegalStateException("desktop not alive:" + desktop); } OperationThread t = (OperationThread) desktop.getAttribute(DESKTOP_KEY); if (t == null) { t = new OperationThread(desktop); if(D.ON && log.debugable()){ log.debug("staring a Operation Thread for desktop:"+desktop+",name="+t.getName()); } desktop.setAttribute(DESKTOP_KEY, t); t.start(); } return t.getQueue(); } } /** * Terminate a {@linkplain OperationThread} which is stored in desktop and clear it. * * @param desktop the associated desktop */ public static void destroyWith(Desktop desktop) { if (desktop == null){ throw new NullPointerException("desktop is null"); } if(D.ON && log.debugable()){ log.debug("destory a Operation Thread for desktop:"+desktop); } synchronized(desktop) { if (desktop.isAlive()) {// destroy desktop if it still alive. OperationThread t = (OperationThread) desktop .getAttribute(DESKTOP_KEY); desktop.removeAttribute(DESKTOP_KEY); if (t != null && t.isRunning()) { t.terminate(); } } } } /** * Is this thread still running * @return true is thread still running */ public boolean isRunning() { return _running; } /** * Terminate this thread. thread will be stopped after last run trip. */ public void terminate() { _running = false; synchronized(_queue) { _queue.notifyAll(); } } public void run() { try { int failCount = 0; while (_running) { if(!_desktop.isAlive()){ throw new DesktopUnavailableException( "Desktop is not alive"+_desktop); } if (_queue.hasElement()) { boolean r = false; try { r = Executions.activate(_desktop, _activateTimeout); } catch (InterruptedException e) { } if (!r) { failCount++; if (failCount >= _maxFailCount) { throw new DesktopUnavailableException( "Fail to Activate Desktop:" + _desktop + " after " + failCount + " times"); } continue; } failCount = 0; // since we have activated desktop, // we execute all operation in queue Operation op = null; try { while (_queue.hasElement()) { op = _queue.next(); op.execute(_desktop); } } catch (Exception x) { // if exception, notify fail. if (op != null) { op.failToExecute(_desktop); } throw x; } finally { Executions.deactivate(_desktop); } } try { // if queue is still empty, and still running then we wait. // queue will be notify when someone put operation to queue // or terminate is invoked check OperationQueue#put synchronized(_queue) { if (_running && !_queue.hasElement()) { //wait just a while, _queue.wait(_waitTimeout); } } } catch (InterruptedException e) { } } } catch (DesktopUnavailableException x) { // send fail to all operation that it can't be execute. if(D.ON && log.debugable()){ log.debug("Desktop not available:" + x.getMessage()); } while (_queue.hasElement()) { Operation op = _queue.next(); op.failToExecute(_desktop); } } catch (Exception x) { log.warning(x); while (_queue.hasElement()) { Operation op = _queue.next(); op.failToExecute(_desktop); } } finally { _running = false; OperationThread.destroyWith(_desktop); //notify all listener thread is destroyed. _queue.fireQueueUnavailable(_desktop); _queue.clearListener(); _desktop = null; _queue = null; if(D.ON && log.debugable()){ log.debug("end of a Operation Thread, name="+this.getName()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy