<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java_Tutorial%2FThread%2FThread_Pool</id>
		<title>Java Tutorial/Thread/Thread Pool - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java_Tutorial%2FThread%2FThread_Pool"/>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java_Tutorial/Thread/Thread_Pool&amp;action=history"/>
		<updated>2026-04-21T22:31:10Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java_Tutorial/Thread/Thread_Pool&amp;diff=2757&amp;oldid=prev</id>
		<title> в 17:44, 31 мая 2010</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java_Tutorial/Thread/Thread_Pool&amp;diff=2757&amp;oldid=prev"/>
				<updated>2010-05-31T17:44:26Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr style=&quot;vertical-align: top;&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Версия 17:44, 31 мая 2010&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; style=&quot;text-align: center;&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
			</entry>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java_Tutorial/Thread/Thread_Pool&amp;diff=2758&amp;oldid=prev</id>
		<title>Admin: 1 версия</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java_Tutorial/Thread/Thread_Pool&amp;diff=2758&amp;oldid=prev"/>
				<updated>2010-05-31T15:18:00Z</updated>
		
		<summary type="html">&lt;p&gt;1 версия&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==  A pool of work threads ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * WorkThreadPool.java - Background thread pool that does stuff&lt;br /&gt;
 * :tabSize=8:indentSize=8:noTabs=false:&lt;br /&gt;
 * :folding=explicit:collapseFolds=1:&lt;br /&gt;
 *&lt;br /&gt;
 * Copyright (C) 2000 Slava Pestov&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or&lt;br /&gt;
 * modify it under the terms of the GNU General Public License&lt;br /&gt;
 * as published by the Free Software Foundation; either version 2&lt;br /&gt;
 * of the License, or any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the Free Software&lt;br /&gt;
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
//{{{ Imports&lt;br /&gt;
import java.util.EventListener;&lt;br /&gt;
import javax.swing.SwingUtilities;&lt;br /&gt;
import javax.swing.event.EventListenerList;&lt;br /&gt;
//}}}&lt;br /&gt;
/**&lt;br /&gt;
 * A pool of work threads.&lt;br /&gt;
 * &lt;br /&gt;
 * @author Slava Pestov&lt;br /&gt;
 * @version $Id: WorkThreadPool.java 12504 2008-04-22 23:12:43Z ezust $&lt;br /&gt;
 * @see org.gjt.sp.util.WorkThread&lt;br /&gt;
 * @since jEdit 2.6pre1&lt;br /&gt;
 */&lt;br /&gt;
public class WorkThreadPool {&lt;br /&gt;
  // {{{ WorkThreadPool constructor&lt;br /&gt;
  /**&lt;br /&gt;
   * Creates a new work thread pool with the specified number of work threads.&lt;br /&gt;
   * &lt;br /&gt;
   * @param name&lt;br /&gt;
   *          The thread name prefix&lt;br /&gt;
   * @param count&lt;br /&gt;
   *          The number of work threads&lt;br /&gt;
   */&lt;br /&gt;
  public WorkThreadPool(String name, int count) {&lt;br /&gt;
    listenerList = new EventListenerList();&lt;br /&gt;
    if (count != 0) {&lt;br /&gt;
      threadGroup = new ThreadGroup(name);&lt;br /&gt;
      threads = new WorkThread[count];&lt;br /&gt;
      for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
        threads[i] = new WorkThread(this, threadGroup, name + &amp;quot; #&amp;quot; + (i + 1));&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ start() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Starts all the threads in this thread pool.&lt;br /&gt;
   */&lt;br /&gt;
  public void start() {&lt;br /&gt;
    /* not really needed since threads don&amp;quot;t start until after */&lt;br /&gt;
    synchronized (lock) {&lt;br /&gt;
      started = true;&lt;br /&gt;
      if (awtRequestCount != 0 &amp;amp;&amp;amp; requestCount == 0)&lt;br /&gt;
        queueAWTRunner();&lt;br /&gt;
    }&lt;br /&gt;
    if (threads != null) {&lt;br /&gt;
      for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
        threads[i].start();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ addWorkRequest() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Adds a work request to the queue.&lt;br /&gt;
   * &lt;br /&gt;
   * @param run&lt;br /&gt;
   *          The runnable&lt;br /&gt;
   * @param inAWT&lt;br /&gt;
   *          If true, will be executed in AWT thread. Otherwise, will be&lt;br /&gt;
   *          executed in work thread&lt;br /&gt;
   */&lt;br /&gt;
  public void addWorkRequest(Runnable run, boolean inAWT) {&lt;br /&gt;
    if (threads == null) {&lt;br /&gt;
      run.run();&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    synchronized (lock) {&lt;br /&gt;
      // {{{ if there are no requests, execute AWT requests immediately&lt;br /&gt;
      if (started &amp;amp;&amp;amp; inAWT &amp;amp;&amp;amp; requestCount == 0 &amp;amp;&amp;amp; awtRequestCount == 0) {&lt;br /&gt;
        // Log.log(Log.DEBUG,this,&amp;quot;AWT immediate: &amp;quot; + run);&lt;br /&gt;
        if (SwingUtilities.isEventDispatchThread())&lt;br /&gt;
          run.run();&lt;br /&gt;
        else&lt;br /&gt;
          SwingUtilities.invokeLater(run);&lt;br /&gt;
        return;&lt;br /&gt;
      } // }}}&lt;br /&gt;
      Request request = new Request(run);&lt;br /&gt;
      // {{{ Add to AWT queue...&lt;br /&gt;
      if (inAWT) {&lt;br /&gt;
        if (firstAWTRequest == null &amp;amp;&amp;amp; lastAWTRequest == null)&lt;br /&gt;
          firstAWTRequest = lastAWTRequest = request;&lt;br /&gt;
        else {&lt;br /&gt;
          lastAWTRequest.next = request;&lt;br /&gt;
          lastAWTRequest = request;&lt;br /&gt;
        }&lt;br /&gt;
        awtRequestCount++;&lt;br /&gt;
        // if no requests are running, requestDone()&lt;br /&gt;
        // will not be called, so we must queue the&lt;br /&gt;
        // AWT runner ourselves.&lt;br /&gt;
        if (started &amp;amp;&amp;amp; requestCount == 0)&lt;br /&gt;
          queueAWTRunner();&lt;br /&gt;
      } // }}}&lt;br /&gt;
      // {{{ Add to work thread queue...&lt;br /&gt;
      else {&lt;br /&gt;
        if (firstRequest == null &amp;amp;&amp;amp; lastRequest == null)&lt;br /&gt;
          firstRequest = lastRequest = request;&lt;br /&gt;
        else {&lt;br /&gt;
          lastRequest.next = request;&lt;br /&gt;
          lastRequest = request;&lt;br /&gt;
        }&lt;br /&gt;
        requestCount++;&lt;br /&gt;
      } // }}}&lt;br /&gt;
      lock.notifyAll();&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ waitForRequests() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Waits until all requests are complete.&lt;br /&gt;
   */&lt;br /&gt;
  public void waitForRequests() {&lt;br /&gt;
    if (threads == null)&lt;br /&gt;
      return;&lt;br /&gt;
    synchronized (waitForAllLock) {&lt;br /&gt;
      while (requestCount != 0) {&lt;br /&gt;
        try {&lt;br /&gt;
          waitForAllLock.wait();&lt;br /&gt;
        } catch (InterruptedException ie) {&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    if (SwingUtilities.isEventDispatchThread()) {&lt;br /&gt;
      // do any queued AWT runnables&lt;br /&gt;
      doAWTRequests();&lt;br /&gt;
    } else {&lt;br /&gt;
      try {&lt;br /&gt;
        SwingUtilities.invokeAndWait(new RunRequestsInAWTThread());&lt;br /&gt;
      } catch (Exception e) {&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ getRequestCount() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the number of pending requests.&lt;br /&gt;
   * &lt;br /&gt;
   * @return the pending request count&lt;br /&gt;
   */&lt;br /&gt;
  public int getRequestCount() {&lt;br /&gt;
    return requestCount;&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ getThreadCount() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the number of threads in this pool.&lt;br /&gt;
   * &lt;br /&gt;
   * @return the thread count&lt;br /&gt;
   */&lt;br /&gt;
  public int getThreadCount() {&lt;br /&gt;
    if (threads == null)&lt;br /&gt;
      return 0;&lt;br /&gt;
    else&lt;br /&gt;
      return threads.length;&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ getThread() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the specified thread.&lt;br /&gt;
   * &lt;br /&gt;
   * @param index&lt;br /&gt;
   *          The index of the thread&lt;br /&gt;
   * @return a WorkThread&lt;br /&gt;
   */&lt;br /&gt;
  public WorkThread getThread(int index) {&lt;br /&gt;
    return threads[index];&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ addProgressListener() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Adds a progress listener to this thread pool.&lt;br /&gt;
   * &lt;br /&gt;
   * @param listener&lt;br /&gt;
   *          The listener&lt;br /&gt;
   */&lt;br /&gt;
  public void addProgressListener(WorkThreadProgressListener listener) {&lt;br /&gt;
    listenerList.add(WorkThreadProgressListener.class, listener);&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ removeProgressListener() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Removes a progress listener from this thread pool.&lt;br /&gt;
   * &lt;br /&gt;
   * @param listener&lt;br /&gt;
   *          The listener&lt;br /&gt;
   */&lt;br /&gt;
  public void removeProgressListener(WorkThreadProgressListener listener) {&lt;br /&gt;
    listenerList.remove(WorkThreadProgressListener.class, listener);&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ Package-private members&lt;br /&gt;
  final Object lock = new Object();&lt;br /&gt;
  final Object waitForAllLock = new Object();&lt;br /&gt;
  // {{{ fireStatusChanged() method&lt;br /&gt;
  void fireStatusChanged(WorkThread thread) {&lt;br /&gt;
    final Object[] listeners = listenerList.getListenerList();&lt;br /&gt;
    if (listeners.length != 0) {&lt;br /&gt;
      int index = 0;&lt;br /&gt;
      for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
        if (threads[i] == thread) {&lt;br /&gt;
          index = i;&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      for (int i = listeners.length - 2; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (listeners[i] == WorkThreadProgressListener.class) {&lt;br /&gt;
          ((WorkThreadProgressListener) listeners[i + 1]).statusUpdate(WorkThreadPool.this, index);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ fireProgressChanged() method&lt;br /&gt;
  void fireProgressChanged(WorkThread thread) {&lt;br /&gt;
    final Object[] listeners = listenerList.getListenerList();&lt;br /&gt;
    if (listeners.length != 0) {&lt;br /&gt;
      int index = 0;&lt;br /&gt;
      for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
        if (threads[i] == thread) {&lt;br /&gt;
          index = i;&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      for (int i = listeners.length - 2; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (listeners[i] == WorkThreadProgressListener.class) {&lt;br /&gt;
          ((WorkThreadProgressListener) listeners[i + 1])&lt;br /&gt;
              .progressUpdate(WorkThreadPool.this, index);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ requestDone() method&lt;br /&gt;
  void requestDone() {&lt;br /&gt;
    synchronized (lock) {&lt;br /&gt;
      requestCount--;&lt;br /&gt;
      if (requestCount == 0 &amp;amp;&amp;amp; firstAWTRequest != null)&lt;br /&gt;
        queueAWTRunner();&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ getNextRequest() method&lt;br /&gt;
  Request getNextRequest() {&lt;br /&gt;
    synchronized (lock) {&lt;br /&gt;
      Request request = firstRequest;&lt;br /&gt;
      if (request == null)&lt;br /&gt;
        return null;&lt;br /&gt;
      firstRequest = firstRequest.next;&lt;br /&gt;
      if (firstRequest == null)&lt;br /&gt;
        lastRequest = null;&lt;br /&gt;
      if (request.alreadyRun)&lt;br /&gt;
        throw new InternalError(&amp;quot;AIEE!!! Request run twice!!! &amp;quot; + request.run);&lt;br /&gt;
      request.alreadyRun = true;&lt;br /&gt;
      /*&lt;br /&gt;
       * StringBuffer buf = new StringBuffer(&amp;quot;request queue is now: &amp;quot;); Request&lt;br /&gt;
       * _request = request.next; while(_request != null) {&lt;br /&gt;
       * buf.append(_request.id); if(_request.next != null) buf.append(&amp;quot;,&amp;quot;);&lt;br /&gt;
       * _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString());&lt;br /&gt;
       */&lt;br /&gt;
      return request;&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // }}}&lt;br /&gt;
  // {{{ Private members&lt;br /&gt;
  // {{{ Instance variables&lt;br /&gt;
  private boolean started;&lt;br /&gt;
  private ThreadGroup threadGroup;&lt;br /&gt;
  private WorkThread[] threads;&lt;br /&gt;
  // Request queue&lt;br /&gt;
  private Request firstRequest;&lt;br /&gt;
  private Request lastRequest;&lt;br /&gt;
  private int requestCount;&lt;br /&gt;
  // AWT thread magic&lt;br /&gt;
  private boolean awtRunnerQueued;&lt;br /&gt;
  private Request firstAWTRequest;&lt;br /&gt;
  private Request lastAWTRequest;&lt;br /&gt;
  private int awtRequestCount;&lt;br /&gt;
  private EventListenerList listenerList;&lt;br /&gt;
  // }}}&lt;br /&gt;
  // {{{ doAWTRequests() method&lt;br /&gt;
  /** Must always be called with the lock held. */&lt;br /&gt;
  private void doAWTRequests() {&lt;br /&gt;
    while (requestCount == 0 &amp;amp;&amp;amp; firstAWTRequest != null) {&lt;br /&gt;
      doAWTRequest(getNextAWTRequest());&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ doAWTRequest() method&lt;br /&gt;
  /**&lt;br /&gt;
   * Must always be called with the lock held.&lt;br /&gt;
   * &lt;br /&gt;
   * @param request&lt;br /&gt;
   *          the request to run&lt;br /&gt;
   */&lt;br /&gt;
  private void doAWTRequest(Request request) {&lt;br /&gt;
    // Log.log(Log.DEBUG,this,&amp;quot;Running in AWT thread: &amp;quot; + request);&lt;br /&gt;
    try {&lt;br /&gt;
      request.run.run();&lt;br /&gt;
    } catch (Throwable t) {&lt;br /&gt;
    }&lt;br /&gt;
    awtRequestCount--;&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ queueAWTRunner() method&lt;br /&gt;
  /** Must always be called with the lock held. */&lt;br /&gt;
  private void queueAWTRunner() {&lt;br /&gt;
    if (!awtRunnerQueued) {&lt;br /&gt;
      awtRunnerQueued = true;&lt;br /&gt;
      SwingUtilities.invokeLater(new RunRequestsInAWTThread());&lt;br /&gt;
      // Log.log(Log.DEBUG,this,&amp;quot;AWT runner queued&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ getNextAWTRequest() method&lt;br /&gt;
  private Request getNextAWTRequest() {&lt;br /&gt;
    Request request = firstAWTRequest;&lt;br /&gt;
    firstAWTRequest = firstAWTRequest.next;&lt;br /&gt;
    if (firstAWTRequest == null)&lt;br /&gt;
      lastAWTRequest = null;&lt;br /&gt;
    if (request.alreadyRun)&lt;br /&gt;
      throw new InternalError(&amp;quot;AIEE!!! Request run twice!!! &amp;quot; + request.run);&lt;br /&gt;
    request.alreadyRun = true;&lt;br /&gt;
    /*&lt;br /&gt;
     * StringBuffer buf = new StringBuffer(&amp;quot;AWT request queue is now: &amp;quot;);&lt;br /&gt;
     * Request _request = request.next; while(_request != null) {&lt;br /&gt;
     * buf.append(_request.id); if(_request.next != null) buf.append(&amp;quot;,&amp;quot;);&lt;br /&gt;
     * _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString());&lt;br /&gt;
     */&lt;br /&gt;
    return request;&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // }}}&lt;br /&gt;
  static int ID;&lt;br /&gt;
  // {{{ Request class&lt;br /&gt;
  static class Request {&lt;br /&gt;
    int id = ++ID;&lt;br /&gt;
    Runnable run;&lt;br /&gt;
    boolean alreadyRun;&lt;br /&gt;
    Request next;&lt;br /&gt;
    Request(Runnable run) {&lt;br /&gt;
      this.run = run;&lt;br /&gt;
    }&lt;br /&gt;
    public String toString() {&lt;br /&gt;
      return &amp;quot;[id=&amp;quot; + id + &amp;quot;,run=&amp;quot; + run + &amp;quot;]&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
  // {{{ RunRequestsInAWTThread class&lt;br /&gt;
  class RunRequestsInAWTThread implements Runnable {&lt;br /&gt;
    public void run() {&lt;br /&gt;
      synchronized (lock) {&lt;br /&gt;
        awtRunnerQueued = false;&lt;br /&gt;
        if (requestCount == 0)&lt;br /&gt;
          doAWTRequests();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } // }}}&lt;br /&gt;
}&lt;br /&gt;
/*&lt;br /&gt;
 * WorkThread.java - Background thread that does stuff Copyright (C) 2000 Slava&lt;br /&gt;
 * Pestov&lt;br /&gt;
 * &lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify it under&lt;br /&gt;
 * the terms of the GNU General Public License as published by the Free Software&lt;br /&gt;
 * Foundation; either version 2 of the License, or any later version.&lt;br /&gt;
 * &lt;br /&gt;
 * This program is distributed in the hope that it will be useful, but WITHOUT&lt;br /&gt;
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS&lt;br /&gt;
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more&lt;br /&gt;
 * details.&lt;br /&gt;
 * &lt;br /&gt;
 * You should have received a copy of the GNU General Public License along with&lt;br /&gt;
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple&lt;br /&gt;
 * Place - Suite 330, Boston, MA 02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
/**&lt;br /&gt;
 * Services work requests in the background.&lt;br /&gt;
 * &lt;br /&gt;
 * @author Slava Pestov&lt;br /&gt;
 * @version $Id: WorkThread.java 12504 2008-04-22 23:12:43Z ezust $&lt;br /&gt;
 */&lt;br /&gt;
class WorkThread extends Thread implements ThreadAbortMonitor {&lt;br /&gt;
  public WorkThread(WorkThreadPool pool, ThreadGroup group, String name) {&lt;br /&gt;
    super(group, name);&lt;br /&gt;
    // so that jEdit doesn&amp;quot;t exit with no views open automatically&lt;br /&gt;
    // setDaemon(true);&lt;br /&gt;
    setPriority(Thread.MIN_PRIORITY);&lt;br /&gt;
    this.pool = pool;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Sets if the current request can be aborted. If set to true and already&lt;br /&gt;
   * aborted, the thread will be stopped&lt;br /&gt;
   * &lt;br /&gt;
   * @param abortable&lt;br /&gt;
   *          true if the WorkThread is abortable&lt;br /&gt;
   * @since jEdit 2.6pre1&lt;br /&gt;
   */&lt;br /&gt;
  public void setAbortable(boolean abortable) {&lt;br /&gt;
    synchronized (abortLock) {&lt;br /&gt;
      this.abortable = abortable;&lt;br /&gt;
      if (aborted)&lt;br /&gt;
        stop(new Abort());&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns if the work thread is currently running a request.&lt;br /&gt;
   * &lt;br /&gt;
   * @return true if a request is currently running&lt;br /&gt;
   */&lt;br /&gt;
  public boolean isRequestRunning() {&lt;br /&gt;
    return requestRunning;&lt;br /&gt;
  }&lt;br /&gt;
  public boolean isAborted() {&lt;br /&gt;
    synchronized (abortLock) {&lt;br /&gt;
      return aborted;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the status text.&lt;br /&gt;
   * &lt;br /&gt;
   * @return the status label&lt;br /&gt;
   */&lt;br /&gt;
  public String getStatus() {&lt;br /&gt;
    return status;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Sets the status text.&lt;br /&gt;
   * &lt;br /&gt;
   * @param status&lt;br /&gt;
   *          the new status of the thread&lt;br /&gt;
   * @since jEdit 2.6pre1&lt;br /&gt;
   */&lt;br /&gt;
  public void setStatus(String status) {&lt;br /&gt;
    this.status = status;&lt;br /&gt;
    pool.fireProgressChanged(this);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the progress value.&lt;br /&gt;
   * &lt;br /&gt;
   * @return the progress value&lt;br /&gt;
   */&lt;br /&gt;
  public int getProgressValue() {&lt;br /&gt;
    return progressValue;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Sets the progress value.&lt;br /&gt;
   * &lt;br /&gt;
   * @param progressValue&lt;br /&gt;
   *          the new progress value&lt;br /&gt;
   * @since jEdit 2.6pre1&lt;br /&gt;
   */&lt;br /&gt;
  public void setProgressValue(int progressValue) {&lt;br /&gt;
    this.progressValue = progressValue;&lt;br /&gt;
    pool.fireProgressChanged(this);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Returns the progress maximum.&lt;br /&gt;
   * &lt;br /&gt;
   * @return the maximum value of the progression&lt;br /&gt;
   */&lt;br /&gt;
  public int getProgressMaximum() {&lt;br /&gt;
    return progressMaximum;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Sets the maximum progress value.&lt;br /&gt;
   * &lt;br /&gt;
   * @param progressMaximum&lt;br /&gt;
   *          the maximum value of the progression&lt;br /&gt;
   * @since jEdit 2.6pre1&lt;br /&gt;
   */&lt;br /&gt;
  public void setProgressMaximum(int progressMaximum) {&lt;br /&gt;
    this.progressMaximum = progressMaximum;&lt;br /&gt;
    pool.fireProgressChanged(this);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Aborts the currently running request, if allowed.&lt;br /&gt;
   * &lt;br /&gt;
   * @since jEdit 2.6pre1&lt;br /&gt;
   */&lt;br /&gt;
  public void abortCurrentRequest() {&lt;br /&gt;
    synchronized (abortLock) {&lt;br /&gt;
      if (abortable &amp;amp;&amp;amp; !aborted)&lt;br /&gt;
        stop(new Abort());&lt;br /&gt;
      aborted = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (;;) {&lt;br /&gt;
      doRequests();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  // private members&lt;br /&gt;
  private WorkThreadPool pool;&lt;br /&gt;
  private final Object abortLock = new Object();&lt;br /&gt;
  private boolean requestRunning;&lt;br /&gt;
  private boolean abortable;&lt;br /&gt;
  private boolean aborted;&lt;br /&gt;
  private String status;&lt;br /&gt;
  private int progressValue;&lt;br /&gt;
  private int progressMaximum;&lt;br /&gt;
  private void doRequests() {&lt;br /&gt;
    WorkThreadPool.Request request;&lt;br /&gt;
    for (;;) {&lt;br /&gt;
      request = pool.getNextRequest();&lt;br /&gt;
      if (request == null)&lt;br /&gt;
        break;&lt;br /&gt;
      else {&lt;br /&gt;
        requestRunning = true;&lt;br /&gt;
        pool.fireStatusChanged(this);&lt;br /&gt;
        doRequest(request);&lt;br /&gt;
        requestRunning = false;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    pool.fireStatusChanged(this);&lt;br /&gt;
    synchronized (pool.waitForAllLock) {&lt;br /&gt;
      // notify a running waitForRequests() method&lt;br /&gt;
      pool.waitForAllLock.notifyAll();&lt;br /&gt;
    }&lt;br /&gt;
    synchronized (pool.lock) {&lt;br /&gt;
      // wait for more requests&lt;br /&gt;
      try {&lt;br /&gt;
        pool.lock.wait();&lt;br /&gt;
      } catch (InterruptedException ie) {&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  private void doRequest(WorkThreadPool.Request request) {&lt;br /&gt;
    try {&lt;br /&gt;
      request.run.run();&lt;br /&gt;
    } catch (Throwable t) {&lt;br /&gt;
    } finally {&lt;br /&gt;
      synchronized (abortLock) {&lt;br /&gt;
        aborted = abortable = false;&lt;br /&gt;
      }&lt;br /&gt;
      status = null;&lt;br /&gt;
      progressValue = progressMaximum = 0;&lt;br /&gt;
      pool.requestDone();&lt;br /&gt;
      pool.fireStatusChanged(this);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  public static class Abort extends Error {&lt;br /&gt;
    public Abort() {&lt;br /&gt;
      super(&amp;quot;Work request aborted&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
/*&lt;br /&gt;
 * ThreadAbortMonitor.java - Thread Abort Monitor&lt;br /&gt;
 * :tabSize=8:indentSize=8:noTabs=false: :folding=explicit:collapseFolds=1:&lt;br /&gt;
 * &lt;br /&gt;
 * Copyright (C) 2006 Matthieu Casanova&lt;br /&gt;
 * &lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify it under&lt;br /&gt;
 * the terms of the GNU General Public License as published by the Free Software&lt;br /&gt;
 * Foundation; either version 2 of the License, or any later version.&lt;br /&gt;
 * &lt;br /&gt;
 * This program is distributed in the hope that it will be useful, but WITHOUT&lt;br /&gt;
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS&lt;br /&gt;
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more&lt;br /&gt;
 * details.&lt;br /&gt;
 * &lt;br /&gt;
 * You should have received a copy of the GNU General Public License along with&lt;br /&gt;
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple&lt;br /&gt;
 * Place - Suite 330, Boston, MA 02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
/**&lt;br /&gt;
 * @author Matthieu Casanova&lt;br /&gt;
 * @author $Id: VFS.java 7129 2006-09-25 20:05:57Z kpouer $&lt;br /&gt;
 */&lt;br /&gt;
interface ThreadAbortMonitor {&lt;br /&gt;
  boolean isAborted();&lt;br /&gt;
}&lt;br /&gt;
/*&lt;br /&gt;
 * WorkThreadProgressListener.java - Progress listener Copyright (C) 2000 Slava&lt;br /&gt;
 * Pestov&lt;br /&gt;
 * &lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify it under&lt;br /&gt;
 * the terms of the GNU General Public License as published by the Free Software&lt;br /&gt;
 * Foundation; either version 2 of the License, or any later version.&lt;br /&gt;
 * &lt;br /&gt;
 * This program is distributed in the hope that it will be useful, but WITHOUT&lt;br /&gt;
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS&lt;br /&gt;
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more&lt;br /&gt;
 * details.&lt;br /&gt;
 * &lt;br /&gt;
 * You should have received a copy of the GNU General Public License along with&lt;br /&gt;
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple&lt;br /&gt;
 * Place - Suite 330, Boston, MA 02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
/**&lt;br /&gt;
 * A work thread execution progress listener.&lt;br /&gt;
 * &lt;br /&gt;
 * @since jEdit 2.6pre1&lt;br /&gt;
 */&lt;br /&gt;
interface WorkThreadProgressListener extends EventListener {&lt;br /&gt;
  // status message changed, operation started, operation ends, ...&lt;br /&gt;
  void statusUpdate(WorkThreadPool threadPool, int threadIndex);&lt;br /&gt;
  // progress bar value change&lt;br /&gt;
  void progressUpdate(WorkThreadPool threadPool, int threadIndex);&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- end source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Simple thread pool. A task is executed by obtaining a thread from the pool ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Licensed to the Apache Software Foundation (ASF) under one&lt;br /&gt;
 * or more contributor license agreements.  See the NOTICE file&lt;br /&gt;
 * distributed with this work for additional information&lt;br /&gt;
 * regarding copyright ownership.  The ASF licenses this file&lt;br /&gt;
 * to you under the Apache License, Version 2.0 (the&lt;br /&gt;
 * &amp;quot;License&amp;quot;); you may not use this file except in compliance&lt;br /&gt;
 * with the License.  You may obtain a copy of the License at&lt;br /&gt;
 *&lt;br /&gt;
 *   http://www.apache.org/licenses/LICENSE-2.0&lt;br /&gt;
 *&lt;br /&gt;
 * Unless required by applicable law or agreed to in writing,&lt;br /&gt;
 * software distributed under the License is distributed on an&lt;br /&gt;
 * &amp;quot;AS IS&amp;quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY&lt;br /&gt;
 * KIND, either express or implied.  See the License for the&lt;br /&gt;
 * specific language governing permissions and limitations&lt;br /&gt;
 * under the License.    &lt;br /&gt;
 */&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
/** Simple thread pool. A task is executed by obtaining a thread from&lt;br /&gt;
 * the pool&lt;br /&gt;
 */&lt;br /&gt;
public class ThreadPool {&lt;br /&gt;
  /** The thread pool contains instances of {@link ThreadPool.Task}.&lt;br /&gt;
   */&lt;br /&gt;
  public interface Task {&lt;br /&gt;
    /** Performs the task.&lt;br /&gt;
     * @throws Throwable The task failed, and the worker thread won&amp;quot;t be used again.&lt;br /&gt;
     */&lt;br /&gt;
    void run() throws Throwable;&lt;br /&gt;
  }&lt;br /&gt;
    /** A task, which may be interrupted, if the pool is shutting down. &lt;br /&gt;
     */&lt;br /&gt;
    public interface InterruptableTask extends Task {&lt;br /&gt;
        /** Interrupts the task.&lt;br /&gt;
         * @throws Throwable Shutting down the task failed.&lt;br /&gt;
         */&lt;br /&gt;
        void shutdown() throws Throwable;&lt;br /&gt;
    }&lt;br /&gt;
    private class Poolable {&lt;br /&gt;
        private boolean shuttingDown;&lt;br /&gt;
        private Task task;&lt;br /&gt;
        private Thread thread;&lt;br /&gt;
        Poolable(ThreadGroup pGroup, int pNum) {&lt;br /&gt;
            thread = new Thread(pGroup, pGroup.getName() + &amp;quot;-&amp;quot; + pNum){&lt;br /&gt;
                public void run() {&lt;br /&gt;
                    while (!isShuttingDown()) {&lt;br /&gt;
                        final Task t = getTask();&lt;br /&gt;
                        if (t == null) {&lt;br /&gt;
                            try {&lt;br /&gt;
                                synchronized (this) {&lt;br /&gt;
                                    if (!isShuttingDown()  &amp;amp;&amp;amp;  getTask() == null) {&lt;br /&gt;
                                        wait();&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            } catch (InterruptedException e) {&lt;br /&gt;
                                // Do nothing&lt;br /&gt;
                            }&lt;br /&gt;
                        } else {&lt;br /&gt;
                            try {&lt;br /&gt;
                                t.run();&lt;br /&gt;
                                resetTask();&lt;br /&gt;
                                repool(Poolable.this);&lt;br /&gt;
                            } catch (Throwable e) {&lt;br /&gt;
                                discard(Poolable.this);&lt;br /&gt;
                                resetTask();&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            };&lt;br /&gt;
            thread.start();&lt;br /&gt;
        }&lt;br /&gt;
        synchronized void shutdown() {&lt;br /&gt;
            shuttingDown = true;&lt;br /&gt;
            final Task t = getTask();&lt;br /&gt;
            if (t != null  &amp;amp;&amp;amp;  t instanceof InterruptableTask) {&lt;br /&gt;
                try {&lt;br /&gt;
                    ((InterruptableTask) t).shutdown();&lt;br /&gt;
                } catch (Throwable th) {&lt;br /&gt;
                    // Ignore me&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            task = null;&lt;br /&gt;
            synchronized (thread) {&lt;br /&gt;
                thread.notify();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        private synchronized boolean isShuttingDown() { return shuttingDown; }&lt;br /&gt;
        String getName() { return thread.getName(); }&lt;br /&gt;
        private synchronized Task getTask() {&lt;br /&gt;
            return task;&lt;br /&gt;
        }&lt;br /&gt;
        private synchronized void resetTask() {&lt;br /&gt;
            task = null;&lt;br /&gt;
        }&lt;br /&gt;
        synchronized void start(Task pTask) {&lt;br /&gt;
            task = pTask;&lt;br /&gt;
            synchronized (thread) {&lt;br /&gt;
                thread.notify();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  private final ThreadGroup threadGroup;&lt;br /&gt;
  private final int maxSize;&lt;br /&gt;
  private final List waitingThreads = new ArrayList();&lt;br /&gt;
  private final List runningThreads = new ArrayList();&lt;br /&gt;
  private final List waitingTasks = new ArrayList();&lt;br /&gt;
  private int num;&lt;br /&gt;
&lt;br /&gt;
  /** Creates a new instance.&lt;br /&gt;
   * @param pMaxSize Maximum number of concurrent threads.&lt;br /&gt;
   * @param pName Thread group name.&lt;br /&gt;
   */&lt;br /&gt;
  public ThreadPool(int pMaxSize, String pName) {&lt;br /&gt;
    maxSize = pMaxSize;&lt;br /&gt;
    threadGroup = new ThreadGroup(pName);&lt;br /&gt;
  }&lt;br /&gt;
  synchronized void discard(Poolable pPoolable) {&lt;br /&gt;
    pPoolable.shutdown();&lt;br /&gt;
        runningThreads.remove(pPoolable);&lt;br /&gt;
        waitingThreads.remove(pPoolable);&lt;br /&gt;
  }&lt;br /&gt;
  synchronized void repool(Poolable pPoolable) {&lt;br /&gt;
        if (runningThreads.remove(pPoolable)) {&lt;br /&gt;
            if (maxSize != 0  &amp;amp;&amp;amp;  runningThreads.size() + waitingThreads.size() &amp;gt;= maxSize) {&lt;br /&gt;
                discard(pPoolable);&lt;br /&gt;
            } else {&lt;br /&gt;
                waitingThreads.add(pPoolable);&lt;br /&gt;
                if (waitingTasks.size() &amp;gt; 0) {&lt;br /&gt;
                    Task task = (Task) waitingTasks.remove(waitingTasks.size() - 1);&lt;br /&gt;
                    startTask(task);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            discard(pPoolable);&lt;br /&gt;
        }&lt;br /&gt;
  }&lt;br /&gt;
  /** Starts a task immediately.&lt;br /&gt;
   * @param pTask The task being started.&lt;br /&gt;
   * @return True, if the task could be started immediately. False, if&lt;br /&gt;
   * the maxmimum number of concurrent tasks was exceeded. If so, you&lt;br /&gt;
   * might consider to use the {@link #addTask(ThreadPool.Task)} method instead.&lt;br /&gt;
   */&lt;br /&gt;
  public synchronized boolean startTask(Task pTask) {&lt;br /&gt;
    if (maxSize != 0  &amp;amp;&amp;amp;  runningThreads.size() &amp;gt;= maxSize) {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
        Poolable poolable;&lt;br /&gt;
    if (waitingThreads.size() &amp;gt; 0) {&lt;br /&gt;
        poolable = (Poolable) waitingThreads.remove(waitingThreads.size()-1);&lt;br /&gt;
    } else {&lt;br /&gt;
            poolable = new Poolable(threadGroup, num++);&lt;br /&gt;
    }&lt;br /&gt;
    runningThreads.add(poolable);&lt;br /&gt;
        poolable.start(pTask);&lt;br /&gt;
    return true;&lt;br /&gt;
  }&lt;br /&gt;
  /** Adds a task for immediate or deferred execution.&lt;br /&gt;
   * @param pTask The task being added.&lt;br /&gt;
   * @return True, if the task was started immediately. False, if&lt;br /&gt;
   * the task will be executed later.&lt;br /&gt;
   */&lt;br /&gt;
  public synchronized boolean addTask(Task pTask) {&lt;br /&gt;
    if (startTask(pTask)) {&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    waitingTasks.add(pTask);&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  /** Closes the pool.&lt;br /&gt;
   */&lt;br /&gt;
  public synchronized void shutdown() {&lt;br /&gt;
        while (!waitingThreads.isEmpty()) {&lt;br /&gt;
            Poolable poolable = (Poolable) waitingThreads.remove(waitingThreads.size()-1);&lt;br /&gt;
            poolable.shutdown();&lt;br /&gt;
        }&lt;br /&gt;
        while (!runningThreads.isEmpty()) {&lt;br /&gt;
            Poolable poolable = (Poolable) runningThreads.remove(runningThreads.size()-1);&lt;br /&gt;
            poolable.shutdown();&lt;br /&gt;
        }&lt;br /&gt;
  }&lt;br /&gt;
  /** Returns the maximum number of concurrent threads.&lt;br /&gt;
   * @return Maximum number of threads.&lt;br /&gt;
   */&lt;br /&gt;
  public int getMaxThreads() { return maxSize; }&lt;br /&gt;
  /** Returns the number of threads, which have actually been created,&lt;br /&gt;
     * as opposed to the number of currently running threads.&lt;br /&gt;
   */&lt;br /&gt;
    public synchronized int getNumThreads() { return num; }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- end source code --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	</feed>