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 task.notifyAll(); 048 } 049 } 050 } catch (Exception e) { 051 e.printStackTrace(); 052 } finally { 053 synchronized (tasks) { 054 terminated=true; 055 tasks.notifyAll(); 056 } 057 } 058 } 059 }; 060 061 Runtime.getRuntime().addShutdownHook(new Thread() { 062 public void run() { 063 synchronized (tasks) { 064 tasks.add(null); 065 tasks.notifyAll(); 066 } 067 } 068 }); 069 } 070 071 private void checkTerminated() { 072 synchronized (tasks) { 073 if (terminated) { 074 throw new IllegalStateException("Task processing thread was terminated prematurely"); 075 } 076 } 077 } 078 079 private boolean terminated; 080 081 /** 082 * Executes task in a separate thread 083 * @throws InterruptedException 084 */ 085 public void execute(Runnable task) throws InterruptedException { 086 if (task!=null) { 087 synchronized (tasks) { 088 checkTerminated(); 089 tasks.add(task); 090 tasks.notifyAll(); 091 } 092 093 synchronized (task) { 094 task.wait(); 095 } 096 } 097 } 098 099 private static SerialProcessor defaultInstance; 100 101 public static SerialProcessor getDefaultInstance() { 102 synchronized (SerialProcessor.class) { 103 if (defaultInstance==null) { 104 defaultInstance=new SerialProcessor(); 105 } 106 } 107 return defaultInstance; 108 } 109 }