blob: 95090412ad4d7fdfc25aeddbf5b468b68f55fd46 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.jmx.snmp.tasks;
27
28import java.util.ArrayList;
29import com.sun.jmx.snmp.tasks.Task;
30import com.sun.jmx.snmp.tasks.TaskServer;
31
32/**
33 * This class implements a {@link com.sun.jmx.snmp.tasks.TaskServer} over
34 * a thread pool.
35 * <p><b>This API is a Sun Microsystems internal API and is subject
36 * to change without notice.</b></p>
37 **/
38public class ThreadService implements TaskServer {
39
40 public ThreadService(int threadNumber) {
41 if (threadNumber <= 0) {
42 throw new IllegalArgumentException("The thread number should bigger than zero.");
43 }
44
45 minThreads = threadNumber;
46 threadList = new ExecutorThread[threadNumber];
47
48// for (int i=0; i<threadNumber; i++) {
49// threadList[i] = new ExecutorThread();
50// threadList[i].start();
51// }
52
53 priority = Thread.currentThread().getPriority();
54 cloader = Thread.currentThread().getContextClassLoader();
55
56//System.out.println("---jsl: ThreadService: running threads = "+threadNumber);
57 }
58
59// public methods
60// --------------
61
62 /**
63 * Submit a task to be executed.
64 * Once a task is submitted, it is guaranteed that either
65 * {@link com.sun.jmx.snmp.tasks.Task#run() task.run()} or
66 * {@link com.sun.jmx.snmp.tasks.Task#cancel() task.cancel()} will be called.
67 * This implementation of TaskServer uses a thread pool to execute
68 * the submitted tasks.
69 * @param task The task to be executed.
70 * @exception IllegalArgumentException if the submitted task is null.
71 **/
72 public void submitTask(Task task) throws IllegalArgumentException {
73 submitTask((Runnable)task);
74 }
75
76 /**
77 * Submit a task to be executed.
78 * This implementation of TaskServer uses a thread pool to execute
79 * the submitted tasks.
80 * @param task The task to be executed.
81 * @exception IllegalArgumentException if the submitted task is null.
82 **/
83 public void submitTask(Runnable task) throws IllegalArgumentException {
84 stateCheck();
85
86 if (task == null) {
87 throw new IllegalArgumentException("No task specified.");
88 }
89
90 synchronized(jobList) {
91 jobList.add(jobList.size(), task);
92//System.out.println("jsl-ThreadService: added job "+addedJobs++);
93
94 jobList.notify();
95 }
96
97 createThread();
98 }
99
100 public Runnable removeTask(Runnable task) {
101 stateCheck();
102
103 Runnable removed = null;
104 synchronized(jobList) {
105 int lg = jobList.indexOf(task);
106 if (lg >= 0) {
107 removed = jobList.remove(lg);
108 }
109 }
110 if (removed != null && removed instanceof Task)
111 ((Task) removed).cancel();
112 return removed;
113 }
114
115 public void removeAll() {
116 stateCheck();
117
118 final Object[] jobs;
119 synchronized(jobList) {
120 jobs = jobList.toArray();
121 jobList.clear();
122 }
123 final int len = jobs.length;
124 for (int i=0; i<len ; i++) {
125 final Object o = jobs[i];
126 if (o!= null && o instanceof Task) ((Task)o).cancel();
127 }
128 }
129
130 // to terminate
131 public void terminate() {
132
133 if (terminated == true) {
134 return;
135 }
136
137 terminated = true;
138
139 synchronized(jobList) {
140 jobList.notifyAll();
141 }
142
143 removeAll();
144
145 for (int i=0; i<currThreds; i++) {
146 try {
147 threadList[i].interrupt();
148 } catch (Exception e) {
149 // TODO
150 }
151 }
152
153 threadList = null;
154 }
155
156// private classes
157// ---------------
158
159 // A thread used to execute jobs
160 //
161 private class ExecutorThread extends Thread {
162 public ExecutorThread() {
163 super(threadGroup, "ThreadService-"+counter++);
164 setDaemon(true);
165
166 // init
167 this.setPriority(priority);
168 this.setContextClassLoader(cloader);
169
170 idle++;
171 }
172
173 public void run() {
174
175 while(!terminated) {
176 Runnable job = null;
177
178 synchronized(jobList) {
179 if (jobList.size() > 0) {
180 job = jobList.remove(0);
181 if (jobList.size() > 0) {
182 jobList.notify();
183 }
184
185 } else {
186 try {
187 jobList.wait();
188 } catch (InterruptedException ie) {
189 // terminated ?
190 } finally {
191 }
192 continue;
193 }
194 }
195 if (job != null) {
196 try {
197 idle--;
198 job.run();
199//System.out.println("jsl-ThreadService: done job "+doneJobs++);
200
201 } catch (Exception e) {
202 // TODO
203 e.printStackTrace();
204 } finally {
205 idle++;
206 }
207 }
208
209 // re-init
210 this.setPriority(priority);
211 this.interrupted();
212 this.setContextClassLoader(cloader);
213 }
214 }
215 }
216
217// private methods
218 private void stateCheck() throws IllegalStateException {
219 if (terminated) {
220 throw new IllegalStateException("The thread service has been terminated.");
221 }
222 }
223
224 private void createThread() {
225 if (idle < 1) {
226 synchronized(threadList) {
227 if (jobList.size() > 0 && currThreds < minThreads) {
228 ExecutorThread et = new ExecutorThread();
229 et.start();
230 threadList[currThreds++] = et;
231//System.out.println("jsl-ThreadService: create new thread: "+currThreds);
232 }
233 }
234 }
235 }
236
237
238// protected or private variables
239// ------------------------------
240 private ArrayList<Runnable> jobList = new ArrayList<Runnable>(0);
241
242 private ExecutorThread[] threadList;
243 private int minThreads = 1;
244 private int currThreds = 0;
245 private int idle = 0;
246
247 private boolean terminated = false;
248 private int priority;
249 private ThreadGroup threadGroup = new ThreadGroup("ThreadService");
250 private ClassLoader cloader;
251
252 private static long counter = 0;
253
254 private int addedJobs = 1;
255 private int doneJobs = 1;
256}