KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > foxtrot > workers > SingleWorkerThread


1 /**
2  * Copyright (c) 2002-2005, Simone Bordet
3  * All rights reserved.
4  *
5  * This software is distributable under the BSD license.
6  * See the terms of the BSD license in the documentation provided with this software.
7  */

8
9 package foxtrot.workers;
10
11 import foxtrot.AbstractWorkerThread;
12 import foxtrot.Task;
13
14 /**
15  * Full implementation of {@link foxtrot.WorkerThread} that uses a single worker thread to run
16  * {@link foxtrot.Task}s subclasses. <br />
17  * Tasks execution is serialized: tasks are enqueued and executed one after the other.
18  * @version $Revision: 1.5 $
19  */

20 public class SingleWorkerThread extends AbstractWorkerThread implements Runnable JavaDoc
21 {
22    private static int sequence = 0;
23    static final boolean debug = false;
24
25    private Thread JavaDoc thread;
26    private Link current;
27    private boolean pending;
28
29    public void start()
30    {
31       if (isAlive()) return;
32       if (debug) System.out.println("[SingleWorkerThread] Starting");
33
34       stop();
35
36       thread = new Thread JavaDoc(this, getThreadName());
37       // Daemon, since the JVM should shut down on Event Dispatch Thread termination
38
thread.setDaemon(true);
39       thread.start();
40    }
41
42    /**
43     * Returns the name of the worker thread used by this WorkerThread.
44     */

45    protected String JavaDoc getThreadName()
46    {
47       return "Foxtrot Single Worker Thread #" + nextSequence();
48    }
49
50    static synchronized int nextSequence()
51    {
52       return ++sequence;
53    }
54
55    /**
56     * Stops abruptly this WorkerThread.
57     * If a Task is executing, its execution will be completed,
58     * but pending tasks will not be executed until a restart()
59     */

60    protected void stop()
61    {
62       if (thread != null)
63       {
64          if (debug) System.out.println("[SingleWorkerThread] Ending " + thread);
65          thread.interrupt();
66       }
67    }
68
69    public boolean isAlive()
70    {
71       if (thread == null) return false;
72       return thread.isAlive() && !isThreadInterrupted();
73    }
74
75    public boolean isWorkerThread()
76    {
77       return Thread.currentThread() == thread;
78    }
79
80    /**
81     * Posts the given Task onto an internal queue.
82     * @see #takeTask
83     */

84    public void postTask(Task t)
85    {
86       // It is possible that the worker thread is stopped when an applet is destroyed.
87
// Here we restart it in case has been stopped.
88
// Useful also if the WorkerThread has been replaced but not started by the user
89
if (!isAlive()) start();
90
91       // Synchronized since the variable current is accessed from two threads.
92
// See takeTask()
93
synchronized (this)
94       {
95          if (hasTasks())
96          {
97             if (debug) System.out.println("[SingleWorkerThread] Task queue not empty, enqueueing task:" + t);
98
99             // Append the given task at the end of the queue
100
Link item = current;
101             while (item.next != null) item = item.next;
102             item.next = new Link(t);
103          }
104          else
105          {
106             if (debug) System.out.println("[SingleWorkerThread] Task queue empty, adding task:" + t);
107
108             // Add the given task and notify waiting
109
current = new Link(t);
110             notifyAll();
111          }
112       }
113    }
114
115    /**
116     * Removes and returns the first available {@link foxtrot.Task} from the internal queue.
117     * If no Tasks are available, this method blocks until a Task is posted via
118     * {@link #postTask}
119     */

120    protected Task takeTask() throws InterruptedException JavaDoc
121    {
122       // Synchronized since the variable current is accessed from two threads.
123
// See postTask()
124
synchronized (this)
125       {
126          while (!hasTasks())
127          {
128             if (debug) System.out.println("[SingleWorkerThread] Task queue empty, waiting for tasks");
129             pending = false;
130             wait();
131          }
132          pending = true;
133          // Taking the current task, removing it from the queue
134
Task t = current.task;
135          current = current.next;
136          return t;
137       }
138    }
139
140    private boolean hasTasks()
141    {
142       synchronized (this)
143       {
144          return current != null;
145       }
146    }
147
148    boolean hasPendingTasks()
149    {
150       synchronized (this)
151       {
152          return pending;
153       }
154    }
155
156    /**
157     * Returns whether the worker thread has been interrupted or not.
158     * @see java.lang.Thread#isInterrupted
159     */

160    protected boolean isThreadInterrupted()
161    {
162       return thread.isInterrupted();
163    }
164
165    /**
166     * The worker thread dequeues one {@link foxtrot.Task} from the internal queue via {@link #takeTask}
167     * and then executes it.
168     */

169    public void run()
170    {
171       if (debug) System.out.println("[SingleWorkerThread] Started " + thread);
172
173       while (!isThreadInterrupted())
174       {
175          try
176          {
177             Task t = takeTask();
178             if (debug) System.out.println("[SingleWorkerThread] Dequeued Task " + t);
179             run(t);
180          }
181          catch (InterruptedException JavaDoc x)
182          {
183             if (debug) System.out.println("[SingleWorkerThread] Interrupted " + thread);
184             Thread.currentThread().interrupt();
185             break;
186          }
187       }
188    }
189
190    /**
191     * Executes the given {@link foxtrot.Task}.
192     * This implementation will just call {@link #runTask}.
193     */

194    protected void run(Task task)
195    {
196       runTask(task);
197    }
198
199    private static class Link
200    {
201       private Link next;
202       private final Task task;
203
204       private Link(Task task)
205       {
206          this.task = task;
207       }
208    }
209 }
210
Popular Tags