Text-to-Speech and Concurrency
===



> **Write code for a sample text-to-speech class(es), and then analyze it for potential concurrency issues.**

Below is the code for my attempt at the question, using a BlockingQueue and separate thread to process requests.  I'm not exactly sure what the question is meant to test, but I took it as an example of how to use a queue for requests and how to stop a service.  This implementation is modeled after the logging service in Brian Goetz's book. Any suggestions for improvement are much appreciated.  Thanks. 

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    import com.sun.speech.freetts.Voice;
    import com.sun.speech.freetts.VoiceManager;
    
    public class TextToSpeechService {
    	private final static int CAPACITY = 10;
    	private final BlockingQueue<String> queue;
    	private final SpeakerThread speakerThread;
    	private boolean isShutdown;
    	private int reservations;
    
    	public TextToSpeechService(Voice voice) {
    		this.queue = new LinkedBlockingQueue<String>(CAPACITY);
    		this.speakerThread = new SpeakerThread(voice);
    	}
    
    	public void start() {
    		speakerThread.start(); //Only 1 thread is spawned
    	}
    
    	public void stop() {
    		synchronized (this) {
    			isShutdown = true;
    		}
    	}
    
    	//Producer method: Multiple threads can call this
    	public void speak(String msg) throws InterruptedException {
    		synchronized (this) {
    			if (isShutdown)
    				throw new IllegalStateException("No more requests: Server is shutting down.");
    			reservations++;
    		}
    		queue.put(msg); //Moved out of sync block
    	}
    
    	//Consumer thread
    	private class SpeakerThread extends Thread {
    		private final Voice voice;
    
    		public SpeakerThread(Voice voice) {
    			this.voice = voice;
    		}
    
    		public void run() {
    			while (true) {
    				try {
    					synchronized (this) {
    						if (isShutdown && reservations == 0)
    							break;
    					}
    					String msg = queue.take();
    					synchronized (this) {
    						--reservations;
    					}
    					voice.speak(msg);
    				} catch (InterruptedException e) { /* retry */
    				}
    			}
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException {
    		Voice voice = VoiceManager.getInstance().getVoice("kevin16");
    		voice.allocate();		
    		TextToSpeechService tts = new TextToSpeechService(voice);
    		tts.start();
    		for (int i = 0; i < CAPACITY + 5; i++) {
    			tts.speak("Hello #" + i);
    		}
    		tts.stop();
    	}
    }