001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.util; 005 006 import java.util.LinkedList; 007 008 /** 009 * Processes tasks from differen threads in a single thread. 010 * @author Pavel Vlasov 011 * @version $Revision: 1.6 $ 012 */ 013 public class SerialProcessor { 014 015 private LinkedList tasks=new LinkedList(); 016 017 { 018 new Thread() { 019 { 020 setName("Task processing thread"); 021 start(); 022 } 023 024 public void run() { 025 try { 026 while (true) { 027 Runnable task; 028 synchronized (tasks) { 029 while (tasks.isEmpty()) { 030 try { 031 tasks.wait(); 032 } catch (InterruptedException e) { 033 return; 034 } 035 } 036 037 task=(Runnable) tasks.removeFirst(); 038 } 039 040 if (task==null) { 041 return; 042 } 043 044 try { 045 task.run(); 046 } finally { 047 synchronized (task) { 048 task.notifyAll(); 049 } 050 } 051 } 052 } catch (Exception e) { 053 e.printStackTrace(); 054 } finally { 055 synchronized (tasks) { 056 terminated=true; 057 tasks.notifyAll(); 058 } 059 } 060 } 061 }; 062 063 Runtime.getRuntime().addShutdownHook(new Thread() { 064 public void run() { 065 synchronized (tasks) { 066 tasks.add(null); 067 tasks.notifyAll(); 068 } 069 } 070 }); 071 } 072 073 private void checkTerminated() { 074 synchronized (tasks) { 075 if (terminated) { 076 throw new IllegalStateException("Task processing thread was terminated prematurely"); 077 } 078 } 079 } 080 081 private boolean terminated; 082 083 /** 084 * Executes task in a separate thread 085 * @throws InterruptedException 086 */ 087 public void execute(Runnable task) throws InterruptedException { 088 if (task!=null) { 089 synchronized (tasks) { 090 checkTerminated(); 091 tasks.add(task); 092 tasks.notifyAll(); 093 } 094 095 synchronized (task) { 096 task.wait(); 097 } 098 } 099 } 100 101 private static SerialProcessor defaultInstance; 102 103 public static SerialProcessor getDefaultInstance() { 104 synchronized (SerialProcessor.class) { 105 if (defaultInstance==null) { 106 defaultInstance=new SerialProcessor(); 107 } 108 } 109 return defaultInstance; 110 } 111 }