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    }