A pool of work threads : SwingWorker « Swing JFC « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Class
8. Collections Data Structure
9. Data Type
10. Database SQL JDBC
11. Design Pattern
12. Development Class
13. EJB3
14. Email
15. Event
16. File Input Output
17. Game
18. Generics
19. GWT
20. Hibernate
21. I18N
22. J2EE
23. J2ME
24. JDK 6
25. JNDI LDAP
26. JPA
27. JSP
28. JSTL
29. Language Basics
30. Network Protocol
31. PDF RTF
32. Reflection
33. Regular Expressions
34. Scripting
35. Security
36. Servlets
37. Spring
38. Swing Components
39. Swing JFC
40. SWT JFace Eclipse
41. Threads
42. Tiny Application
43. Velocity
44. Web Services SOA
45. XML
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java » Swing JFC » SwingWorkerScreenshots 
A pool of work threads
   
/*
 * WorkThreadPool.java - Background thread pool that does stuff
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 2000 Slava Pestov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//{{{ Imports
import java.util.EventListener;

import javax.swing.SwingUtilities;
import javax.swing.event.EventListenerList;

//}}}

/**
 * A pool of work threads.
 
 @author Slava Pestov
 @version $Id: WorkThreadPool.java 12504 2008-04-22 23:12:43Z ezust $
 @see org.gjt.sp.util.WorkThread
 @since jEdit 2.6pre1
 */
public class WorkThreadPool {
  // {{{ WorkThreadPool constructor
  /**
   * Creates a new work thread pool with the specified number of work threads.
   
   @param name
   *          The thread name prefix
   @param count
   *          The number of work threads
   */
  public WorkThreadPool(String name, int count) {
    listenerList = new EventListenerList();

    if (count != 0) {
      threadGroup = new ThreadGroup(name);
      threads = new WorkThread[count];
      for (int i = 0; i < threads.length; i++) {
        threads[inew WorkThread(this, threadGroup, name + " #" (i + 1));
      }
    }

  // }}}

  // {{{ start() method
  /**
   * Starts all the threads in this thread pool.
   */
  public void start() {
    /* not really needed since threads don't start until after */
    synchronized (lock) {
      started = true;

      if (awtRequestCount != && requestCount == 0)
        queueAWTRunner();
    }

    if (threads != null) {
      for (int i = 0; i < threads.length; i++) {
        threads[i].start();
      }
    }
  // }}}

  // {{{ addWorkRequest() method
  /**
   * Adds a work request to the queue.
   
   @param run
   *          The runnable
   @param inAWT
   *          If true, will be executed in AWT thread. Otherwise, will be
   *          executed in work thread
   */
  public void addWorkRequest(Runnable run, boolean inAWT) {
    if (threads == null) {
      run.run();
      return;
    }

    synchronized (lock) {
      // {{{ if there are no requests, execute AWT requests immediately
      if (started && inAWT && requestCount == && awtRequestCount == 0) {
        // Log.log(Log.DEBUG,this,"AWT immediate: " + run);

        if (SwingUtilities.isEventDispatchThread())
          run.run();
        else
          SwingUtilities.invokeLater(run);

        return;
      // }}}

      Request request = new Request(run);

      // {{{ Add to AWT queue...
      if (inAWT) {
        if (firstAWTRequest == null && lastAWTRequest == null)
          firstAWTRequest = lastAWTRequest = request;
        else {
          lastAWTRequest.next = request;
          lastAWTRequest = request;
        }

        awtRequestCount++;

        // if no requests are running, requestDone()
        // will not be called, so we must queue the
        // AWT runner ourselves.
        if (started && requestCount == 0)
          queueAWTRunner();
      // }}}
      // {{{ Add to work thread queue...
      else {
        if (firstRequest == null && lastRequest == null)
          firstRequest = lastRequest = request;
        else {
          lastRequest.next = request;
          lastRequest = request;
        }

        requestCount++;
      // }}}

      lock.notifyAll();
    }
  // }}}

  // {{{ waitForRequests() method
  /**
   * Waits until all requests are complete.
   */
  public void waitForRequests() {
    if (threads == null)
      return;

    synchronized (waitForAllLock) {
      while (requestCount != 0) {
        try {
          waitForAllLock.wait();
        catch (InterruptedException ie) {

        }
      }
    }

    if (SwingUtilities.isEventDispatchThread()) {
      // do any queued AWT runnables
      doAWTRequests();
    else {
      try {
        SwingUtilities.invokeAndWait(new RunRequestsInAWTThread());
      catch (Exception e) {

      }
    }
  // }}}

  // {{{ getRequestCount() method
  /**
   * Returns the number of pending requests.
   
   @return the pending request count
   */
  public int getRequestCount() {
    return requestCount;
  // }}}

  // {{{ getThreadCount() method
  /**
   * Returns the number of threads in this pool.
   
   @return the thread count
   */
  public int getThreadCount() {
    if (threads == null)
      return 0;
    else
      return threads.length;
  // }}}

  // {{{ getThread() method
  /**
   * Returns the specified thread.
   
   @param index
   *          The index of the thread
   @return a WorkThread
   */
  public WorkThread getThread(int index) {
    return threads[index];
  // }}}

  // {{{ addProgressListener() method
  /**
   * Adds a progress listener to this thread pool.
   
   @param listener
   *          The listener
   */
  public void addProgressListener(WorkThreadProgressListener listener) {
    listenerList.add(WorkThreadProgressListener.class, listener);
  // }}}

  // {{{ removeProgressListener() method
  /**
   * Removes a progress listener from this thread pool.
   
   @param listener
   *          The listener
   */
  public void removeProgressListener(WorkThreadProgressListener listener) {
    listenerList.remove(WorkThreadProgressListener.class, listener);
  // }}}

  // {{{ Package-private members
  final Object lock = new Object();

  final Object waitForAllLock = new Object();

  // {{{ fireStatusChanged() method
  void fireStatusChanged(WorkThread thread) {
    final Object[] listeners = listenerList.getListenerList();
    if (listeners.length != 0) {
      int index = 0;
      for (int i = 0; i < threads.length; i++) {
        if (threads[i== thread) {
          index = i;
          break;
        }
      }

      for (int i = listeners.length - 2; i >= 0; i--) {
        if (listeners[i== WorkThreadProgressListener.class) {
          ((WorkThreadProgressListenerlisteners[i + 1]).statusUpdate(WorkThreadPool.this, index);
        }
      }
    }
  // }}}

  // {{{ fireProgressChanged() method
  void fireProgressChanged(WorkThread thread) {
    final Object[] listeners = listenerList.getListenerList();
    if (listeners.length != 0) {
      int index = 0;
      for (int i = 0; i < threads.length; i++) {
        if (threads[i== thread) {
          index = i;
          break;
        }
      }

      for (int i = listeners.length - 2; i >= 0; i--) {
        if (listeners[i== WorkThreadProgressListener.class) {
          ((WorkThreadProgressListenerlisteners[i + 1])
              .progressUpdate(WorkThreadPool.this, index);
        }
      }
    }
  // }}}

  // {{{ requestDone() method
  void requestDone() {
    synchronized (lock) {
      requestCount--;

      if (requestCount == && firstAWTRequest != null)
        queueAWTRunner();
    }
  // }}}

  // {{{ getNextRequest() method
  Request getNextRequest() {
    synchronized (lock) {
      Request request = firstRequest;
      if (request == null)
        return null;

      firstRequest = firstRequest.next;
      if (firstRequest == null)
        lastRequest = null;

      if (request.alreadyRun)
        throw new InternalError("AIEE!!! Request run twice!!! " + request.run);
      request.alreadyRun = true;

      /*
       * StringBuffer buf = new StringBuffer("request queue is now: "); Request
       * _request = request.next; while(_request != null) {
       * buf.append(_request.id); if(_request.next != null) buf.append(",");
       * _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString());
       */

      return request;
    }
  // }}}

  // }}}

  // {{{ Private members

  // {{{ Instance variables
  private boolean started;

  private ThreadGroup threadGroup;

  private WorkThread[] threads;

  // Request queue
  private Request firstRequest;

  private Request lastRequest;

  private int requestCount;

  // AWT thread magic
  private boolean awtRunnerQueued;

  private Request firstAWTRequest;

  private Request lastAWTRequest;

  private int awtRequestCount;

  private EventListenerList listenerList;

  // }}}

  // {{{ doAWTRequests() method
  /** Must always be called with the lock held. */
  private void doAWTRequests() {
    while (requestCount == && firstAWTRequest != null) {
      doAWTRequest(getNextAWTRequest());
    }
  // }}}

  // {{{ doAWTRequest() method
  /**
   * Must always be called with the lock held.
   
   @param request
   *          the request to run
   */
  private void doAWTRequest(Request request) {
    // Log.log(Log.DEBUG,this,"Running in AWT thread: " + request);

    try {
      request.run.run();
    catch (Throwable t) {
    }

    awtRequestCount--;
  // }}}

  // {{{ queueAWTRunner() method
  /** Must always be called with the lock held. */
  private void queueAWTRunner() {
    if (!awtRunnerQueued) {
      awtRunnerQueued = true;
      SwingUtilities.invokeLater(new RunRequestsInAWTThread());
      // Log.log(Log.DEBUG,this,"AWT runner queued");
    }
  // }}}

  // {{{ getNextAWTRequest() method
  private Request getNextAWTRequest() {
    Request request = firstAWTRequest;
    firstAWTRequest = firstAWTRequest.next;
    if (firstAWTRequest == null)
      lastAWTRequest = null;

    if (request.alreadyRun)
      throw new InternalError("AIEE!!! Request run twice!!! " + request.run);
    request.alreadyRun = true;

    /*
     * StringBuffer buf = new StringBuffer("AWT request queue is now: ");
     * Request _request = request.next; while(_request != null) {
     * buf.append(_request.id); if(_request.next != null) buf.append(",");
     * _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString());
     */

    return request;
  // }}}

  // }}}

  static int ID;

  // {{{ Request class
  static class Request {
    int id = ++ID;

    Runnable run;

    boolean alreadyRun;

    Request next;

    Request(Runnable run) {
      this.run = run;
    }

    public String toString() {
      return "[id=" + id + ",run=" + run + "]";
    }
  // }}}

  // {{{ RunRequestsInAWTThread class
  class RunRequestsInAWTThread implements Runnable {
    public void run() {
      synchronized (lock) {
        awtRunnerQueued = false;
        if (requestCount == 0)
          doAWTRequests();
      }
    }
  // }}}
}

/*
 * WorkThread.java - Background thread that does stuff Copyright (C) 2000 Slava
 * Pestov
 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or any later version.
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/**
 * Services work requests in the background.
 
 @author Slava Pestov
 @version $Id: WorkThread.java 12504 2008-04-22 23:12:43Z ezust $
 */
class WorkThread extends Thread implements ThreadAbortMonitor {
  public WorkThread(WorkThreadPool pool, ThreadGroup group, String name) {
    super(group, name);
    // so that jEdit doesn't exit with no views open automatically
    // setDaemon(true);
    setPriority(Thread.MIN_PRIORITY);

    this.pool = pool;
  }

  /**
   * Sets if the current request can be aborted. If set to true and already
   * aborted, the thread will be stopped
   
   @param abortable
   *          true if the WorkThread is abortable
   @since jEdit 2.6pre1
   */
  public void setAbortable(boolean abortable) {
    synchronized (abortLock) {
      this.abortable = abortable;
      if (aborted)
        stop(new Abort());
    }
  }

  /**
   * Returns if the work thread is currently running a request.
   
   @return true if a request is currently running
   */
  public boolean isRequestRunning() {
    return requestRunning;
  }

  public boolean isAborted() {
    synchronized (abortLock) {
      return aborted;
    }
  }

  /**
   * Returns the status text.
   
   @return the status label
   */
  public String getStatus() {
    return status;
  }

  /**
   * Sets the status text.
   
   @param status
   *          the new status of the thread
   @since jEdit 2.6pre1
   */
  public void setStatus(String status) {
    this.status = status;
    pool.fireProgressChanged(this);
  }

  /**
   * Returns the progress value.
   
   @return the progress value
   */
  public int getProgressValue() {
    return progressValue;
  }

  /**
   * Sets the progress value.
   
   @param progressValue
   *          the new progress value
   @since jEdit 2.6pre1
   */
  public void setProgressValue(int progressValue) {
    this.progressValue = progressValue;
    pool.fireProgressChanged(this);
  }

  /**
   * Returns the progress maximum.
   
   @return the maximum value of the progression
   */
  public int getProgressMaximum() {
    return progressMaximum;
  }

  /**
   * Sets the maximum progress value.
   
   @param progressMaximum
   *          the maximum value of the progression
   @since jEdit 2.6pre1
   */
  public void setProgressMaximum(int progressMaximum) {
    this.progressMaximum = progressMaximum;
    pool.fireProgressChanged(this);
  }

  /**
   * Aborts the currently running request, if allowed.
   
   @since jEdit 2.6pre1
   */
  public void abortCurrentRequest() {
    synchronized (abortLock) {
      if (abortable && !aborted)
        stop(new Abort());
      aborted = true;
    }
  }

  public void run() {

    for (;;) {
      doRequests();
    }
  }

  // private members
  private WorkThreadPool pool;

  private final Object abortLock = new Object();

  private boolean requestRunning;

  private boolean abortable;

  private boolean aborted;

  private String status;

  private int progressValue;

  private int progressMaximum;

  private void doRequests() {
    WorkThreadPool.Request request;
    for (;;) {
      request = pool.getNextRequest();
      if (request == null)
        break;
      else {
        requestRunning = true;
        pool.fireStatusChanged(this);
        doRequest(request);
        requestRunning = false;
      }
    }

    pool.fireStatusChanged(this);

    synchronized (pool.waitForAllLock) {
      // notify a running waitForRequests() method
      pool.waitForAllLock.notifyAll();
    }

    synchronized (pool.lock) {
      // wait for more requests
      try {
        pool.lock.wait();
      catch (InterruptedException ie) {

      }
    }
  }

  private void doRequest(WorkThreadPool.Request request) {

    try {
      request.run.run();
    catch (Throwable t) {

    finally {
      synchronized (abortLock) {
        aborted = abortable = false;
      }
      status = null;
      progressValue = progressMaximum = 0;
      pool.requestDone();
      pool.fireStatusChanged(this);
    }
  }

  public static class Abort extends Error {
    public Abort() {
      super("Work request aborted");
    }
  }
}

/*
 * ThreadAbortMonitor.java - Thread Abort Monitor
 * :tabSize=8:indentSize=8:noTabs=false: :folding=explicit:collapseFolds=1:
 
 * Copyright (C) 2006 Matthieu Casanova
 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or any later version.
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/**
 @author Matthieu Casanova
 @author $Id: VFS.java 7129 2006-09-25 20:05:57Z kpouer $
 */
interface ThreadAbortMonitor {
  boolean isAborted();
}

/*
 * WorkThreadProgressListener.java - Progress listener Copyright (C) 2000 Slava
 * Pestov
 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or any later version.
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/**
 * A work thread execution progress listener.
 
 @since jEdit 2.6pre1
 */
interface WorkThreadProgressListener extends EventListener {
  // status message changed, operation started, operation ends, ...
  void statusUpdate(WorkThreadPool threadPool, int threadIndex);

  // progress bar value change
  void progressUpdate(WorkThreadPool threadPool, int threadIndex);
}

   
    
    
  
Related examples in the same category
1. Use SwingWorker to perform background tasks
2. Use SwingWorker to wrap time consuming task
3. SwingWorker in Java 6
4. Generic class to dispatch events in a highly reliable way.
5. Detect Event Dispatch Thread rule violations
6. Process On Swing Event Thread
7. 3rd version of SwingWorker
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.