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    }