1 22 23 package org.gjt.sp.util; 24 25 import javax.swing.event.EventListenerList ; 27 import javax.swing.SwingUtilities ; 28 30 37 public class WorkThreadPool 38 { 39 46 public WorkThreadPool(String name, int count) 47 { 48 listenerList = new EventListenerList (); 49 50 if(count != 0) 51 { 52 threadGroup = new ThreadGroup (name); 53 threads = new WorkThread[count]; 54 for(int i = 0; i < threads.length; i++) 55 { 56 threads[i] = new WorkThread(this,threadGroup,name + " #" + (i+1)); 57 } 58 } 59 else 60 Log.log(Log.WARNING,this,"Async I/O disabled"); 61 } 63 67 public void start() 68 { 69 70 synchronized(lock) 71 { 72 started = true; 73 74 if(awtRequestCount != 0 && requestCount == 0) 75 queueAWTRunner(); 76 } 77 78 if(threads != null) 79 { 80 for(int i = 0; i < threads.length; i++) 81 { 82 threads[i].start(); 83 } 84 } 85 } 87 94 public void addWorkRequest(Runnable run, boolean inAWT) 95 { 96 if(threads == null) 97 { 98 run.run(); 99 return; 100 } 101 102 synchronized(lock) 103 { 104 if(started && inAWT && requestCount == 0 && awtRequestCount == 0) 106 { 107 109 if(SwingUtilities.isEventDispatchThread()) 110 run.run(); 111 else 112 SwingUtilities.invokeLater(run); 113 114 return; 115 } 117 Request request = new Request(run); 118 119 if(inAWT) 121 { 122 if(firstAWTRequest == null && lastAWTRequest == null) 123 firstAWTRequest = lastAWTRequest = request; 124 else 125 { 126 lastAWTRequest.next = request; 127 lastAWTRequest = request; 128 } 129 130 awtRequestCount++; 131 132 if(started && requestCount == 0) 136 queueAWTRunner(); 137 } else 140 { 141 if(firstRequest == null && lastRequest == null) 142 firstRequest = lastRequest = request; 143 else 144 { 145 lastRequest.next = request; 146 lastRequest = request; 147 } 148 149 requestCount++; 150 } 152 lock.notifyAll(); 153 } 154 } 156 160 public void waitForRequests() 161 { 162 if(threads == null) 163 return; 164 165 synchronized(waitForAllLock) 166 { 167 while(requestCount != 0) 168 { 169 try 170 { 171 waitForAllLock.wait(); 172 } 173 catch(InterruptedException ie) 174 { 175 Log.log(Log.ERROR,this,ie); 176 } 177 } 178 } 179 180 if(SwingUtilities.isEventDispatchThread()) 181 { 182 doAWTRequests(); 184 } 185 else 186 { 187 try 188 { 189 SwingUtilities.invokeAndWait(new RunRequestsInAWTThread()); 190 } 191 catch(Exception e) 192 { 193 Log.log(Log.ERROR,this,e); 194 } 195 } 196 } 198 202 public int getRequestCount() 203 { 204 return requestCount; 205 } 207 211 public int getThreadCount() 212 { 213 if(threads == null) 214 return 0; 215 else 216 return threads.length; 217 } 219 224 public WorkThread getThread(int index) 225 { 226 return threads[index]; 227 } 229 234 public void addProgressListener(WorkThreadProgressListener listener) 235 { 236 listenerList.add(WorkThreadProgressListener.class,listener); 237 } 239 244 public void removeProgressListener(WorkThreadProgressListener listener) 245 { 246 listenerList.remove(WorkThreadProgressListener.class,listener); 247 } 249 Object lock = new Object (); 251 Object waitForAllLock = new Object (); 252 253 void fireStatusChanged(WorkThread thread) 255 { 256 final Object [] listeners = listenerList.getListenerList(); 257 if(listeners.length != 0) 258 { 259 int index = 0; 260 for(int i = 0; i < threads.length; i++) 261 { 262 if(threads[i] == thread) 263 { 264 index = i; 265 break; 266 } 267 } 268 269 for(int i = listeners.length - 2; i >= 0; i--) 270 { 271 if(listeners[i] == WorkThreadProgressListener.class) 272 { 273 ((WorkThreadProgressListener)listeners[i+1]) 274 .statusUpdate(WorkThreadPool.this,index); 275 } 276 } 277 } 278 } 280 void fireProgressChanged(WorkThread thread) 282 { 283 final Object [] listeners = listenerList.getListenerList(); 284 if(listeners.length != 0) 285 { 286 int index = 0; 287 for(int i = 0; i < threads.length; i++) 288 { 289 if(threads[i] == thread) 290 { 291 index = i; 292 break; 293 } 294 } 295 296 for(int i = listeners.length - 2; i >= 0; i--) 297 { 298 if(listeners[i] == WorkThreadProgressListener.class) 299 { 300 ((WorkThreadProgressListener)listeners[i+1]) 301 .progressUpdate(WorkThreadPool.this,index); 302 } 303 } 304 } 305 } 307 void requestDone() 309 { 310 synchronized(lock) 311 { 312 requestCount--; 313 314 if(requestCount == 0 && firstAWTRequest != null) 315 queueAWTRunner(); 316 } 317 } 319 Request getNextRequest() 321 { 322 synchronized(lock) 323 { 324 Request request = firstRequest; 325 if(request == null) 326 return null; 327 328 firstRequest = firstRequest.next; 329 if(firstRequest == null) 330 lastRequest = null; 331 332 if(request.alreadyRun) 333 throw new InternalError ("AIEE!!! Request run twice!!! " + request.run); 334 request.alreadyRun = true; 335 336 346 347 return request; 348 } 349 } 351 353 355 private boolean started; 357 private ThreadGroup threadGroup; 358 private WorkThread[] threads; 359 360 private Request firstRequest; 362 private Request lastRequest; 363 private int requestCount; 364 365 private boolean awtRunnerQueued; 367 private Request firstAWTRequest; 368 private Request lastAWTRequest; 369 private int awtRequestCount; 370 371 private EventListenerList listenerList; 372 374 376 private void doAWTRequests() 377 { 378 while(requestCount == 0 && firstAWTRequest != null) 379 { 380 doAWTRequest(getNextAWTRequest()); 381 } 382 } 384 386 private void doAWTRequest(Request request) 387 { 388 390 try 391 { 392 request.run.run(); 393 } 394 catch(Throwable t) 395 { 396 Log.log(Log.ERROR,WorkThread.class,"Exception " 397 + "in AWT thread:"); 398 Log.log(Log.ERROR,WorkThread.class,t); 399 } 400 401 awtRequestCount--; 402 } 404 406 private void queueAWTRunner() 407 { 408 if(!awtRunnerQueued) 409 { 410 awtRunnerQueued = true; 411 SwingUtilities.invokeLater(new RunRequestsInAWTThread()); 412 } 414 } 416 private Request getNextAWTRequest() 418 { 419 Request request = firstAWTRequest; 420 firstAWTRequest = firstAWTRequest.next; 421 if(firstAWTRequest == null) 422 lastAWTRequest = null; 423 424 if(request.alreadyRun) 425 throw new InternalError ("AIEE!!! Request run twice!!! " + request.run); 426 request.alreadyRun = true; 427 428 438 439 return request; 440 } 442 444 static int ID; 445 446 static class Request 448 { 449 int id = ++ID; 450 451 Runnable run; 452 453 boolean alreadyRun; 454 455 Request next; 456 457 Request(Runnable run) 458 { 459 this.run = run; 460 } 461 462 public String toString() 463 { 464 return "[id=" + id + ",run=" + run + "]"; 465 } 466 } 468 class RunRequestsInAWTThread implements Runnable 470 { 471 public void run() 472 { 473 synchronized(lock) 474 { 475 awtRunnerQueued = false; 476 if(requestCount == 0) 477 doAWTRequests(); 478 } 479 } 480 } } 482 | Popular Tags |