I yet did not master the skill of concurrency better say I failed on first attempt and since then did not tried, therefore I'm asking for help. Currently I working on JME application where I need to load mp3 files into Player. I'm able to do it with one file, however I'm failing to start playing next one after previous finished. I tried to use Threads but the run() method never get executed.
Basically somewhere in my application I will call method optionSelected(String). The method will start first thread and is supposed to wait till thread ends to start next thread with upload of next mp3 file and play it.

public void optionSelected(String str)
{
    t = new Thread("SEL");
    t.start();
    soundURL ="/sesimulator/res/"+str+".mp3";
    t = new Thread("soundURL");
    t.start();
}

For unknown reason to me the run() method never get executed and application continue with other business.

Recommended Answers

All 10 Replies

I don't think it's the run method that isn't executing, Peter.

I think the problem is that you are not submitting a Runnable target as the argument for the Thread to execute.

I actually don't understand why the Thread class is not abstract if it allows one to simply give a Thread a title, but I will investigate this a bit more thoroughly and help you find a conclusion.

Yes, the Threads in your example don't really do anything. You need to extend Thread and override run() or supply a Runnable to the constructor. Have you looked through the tutorial on concurrency as a starting point?
http://java.sun.com/docs/books/tutorial/essential/concurrency/runthread.html

The java.util.concurrent package adds a lot of new higher level support structure for asynchronous operations as well. It's covered further towards the end of the tutorial trail.

I'm curious, why you are wanting to use separate threads for what seems to be a synchronous process? You describe wanting to process another song after the current one is finished, but haven't mentioned anything that would require a concurrent process.

Just to answer the question on waiting for one thread to finish before starting the next, here's a trivial example using the join() method

public class JoinExample {

    public static void main(String args[]) {
        Thread t1 = new Thread(new FirstTask());
        Thread t2 = new Thread(new SecondTask());
        
        t1.start();
        try {
            // wait for t1 to complete
            t1.join();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        // start the next
        t2.start();
    }
    
    static class FirstTask implements Runnable {
        int counter=0;
        
        public void run() {
            try {
                while (counter<10){
                    System.out.println(++counter);
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    static class SecondTask implements Runnable {
        int counter=64;
        
        public void run() {
            try {
                while (counter<74){
                    System.out.println(Character.toChars(++counter));
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
commented: Thank you for advice +10

Here's yet another example, though probably overkill--

import java.util.concurrent.*;
import java.net.*;

public class ConcurrentExample{

	public final ExecutorService es;
	private Future currentFuture = null;

	public ConcurrentExample(){
		es = Executors.newFixedThreadPool(1);
	}

	public static void main(String... args){

		ConcurrentExample ce = new ConcurrentExample();

		ce.optionSelected("http://www.google.com"); // invokes the run method - main process takes 5 seconds
		ConcurrentExample.advance(4, false); // silently wait 4 seconds before performing new task
		ce.optionSelected("http://www.yahoo.com"); // this request should fail since current request is still occurring
		ConcurrentExample.advance(6, false); // silently wait 6 seconds before performing new task
		ce.optionSelected("http://www.msn.com"); // this request should succeed since the previous task should have finished
		ce.es.shutdownNow(); // shut down processes so the JVM can exit naturally.

	}

	public static void advance(int seconds, boolean displayStatus){
			long first = System.currentTimeMillis(); // get current time
			long second = (seconds * 1000) + first; // get time arg seconds ahead of the first
			int count = 0;

			// while the first time is not equal to the second, assign first to the current time
			while(first < second){

				if((second - first) == 1000 && displayStatus){
					System.out.println( "Second: " + (++count));
				}

				first = System.currentTimeMillis();
			}
	}

	private class Error242 extends Exception{
		public Error242(String arg){
			super(arg);
		}

		public Error242(){
			super("An error occurred with the specified request!\nPlease try again!");
		}
	}

	public void optionSelected(String str){

		// A new thread should only execute after the previous is finished--
		if(currentFuture == null){
			try{
				currentFuture = es.submit(new Request(str));
			}catch(Exception e){
				System.out.println(e);
			}
		}else System.out.println("There is currently a task in process... please wait.");

		/*
		t = new Thread("SEL"); // assuming a seperate repetitive process
		t.start(); // starting that process
		soundURL ="/sesimulator/res/"+str+".mp3"; // process specified by user
		t = new Thread("soundURL"); // assign request
		t.start(); // start request
		*/
	}

/*
	// Probably not needed--

	private Runnable rt = new Runnable(){

		@Override public void run(){
			// task specific to "SEL"


		}
	};
*/

	private class Request implements Runnable{

		private URL userRequest = null;

		public Request(String userURL) throws Error242{
			try{
				userRequest = new URL(userURL);
			}catch(MalformedURLException me){
				// send error to some log for statistical reasons...
				throw new Error242(); // a more user-friendly error
			}
		}

		@Override public void run(){
			// task specific to SEL
			// task to be performed based on the user's request

			// dummy task to test the logic--
			ConcurrentExample.advance(5, true); // loudly wait 5 seconds
			// finally set the currentFuture to be null when the process is finished--
			currentFuture = null;
		}
	}
}
commented: Thank you for advise +10

Thanx guys, I will play around with these examples. Already see few of the mistakes. Sorry that I can not provide more details as it is MSc project and I do not want to get my back side nailed for plagiarism (not now for sure) .
Can you suggest some easy reading on concurrency (I like reading in style of Deitel or OReilly books, explanation with plenty of examples to try out)? My teacher was useless, about 3/4 of the class failed module, it was university record that may not ever be challenged :D

Sometimes the best way to test to see if something is concurrent or not is to use a tracing technique.

Basically split the code that is shared by threads onto different pieces of paper and pretend that one each paper resembles a Thread attempting to access or perform an operation.

If two threads enter the same function, is the function Thread safe? Are you accessing a reference of one object between two threads? Are you doing initialization that may not be thread safe (basically, both Threads may pass a particular condition test and cause something to be initialized twice) ?

The above code I provided is actually not thread safe, now that I think about it. If two threads are accessing the optionSelected(String) method and they are nearly as fast as each other, then there may be 2 requests to submit 2 different threads, however in this case it's even worse because the ExecutorService is initialized with 1 reusable Thread which means the other request may or may not be tossed aside. Even if it is tossed aside, it's still poor programming practice to simply leave it up to objects to handle errors that they were not defined to handle.

In this event I'd use a Double-Checked lock, so that when the method is called the first time it is synchronized upon a lock object and initialized properly. Afterward, there should be no cost of synchronization when a Thread is already doing its job.

An example--

import java.util.concurrent.*;
import java.net.*;

public class ConcurrentExample{

	public final ExecutorService es;
	private volatile Future currentFuture = null; // if multiple threads share access to changing reference,
												  // then [merely guessing] they need to be able to notice changes done to
												  // shared reference.
	private Object lockObject = new Object();

	public ConcurrentExample(){
		es = Executors.newFixedThreadPool(1);
	}

	public static void main(String... args){

		ConcurrentExample ce = new ConcurrentExample();

		ce.optionSelected("http://www.google.com"); // invokes the run method - main process takes 5 seconds
		ConcurrentExample.advance(4, false); // silently wait 4 seconds before performing new task
		ce.optionSelected("http://www.yahoo.com"); // this request should fail since current request is still occurring
		ConcurrentExample.advance(6, false); // silently wait 6 seconds before performing new task
		ce.optionSelected("http://www.msn.com"); // this request should succeed since the previous task should have finished
		ce.es.shutdownNow(); // shut down processes so the JVM can exit naturally.

	}

	public static void advance(int seconds, boolean displayStatus){
			long first = System.currentTimeMillis(); // get current time
			long second = (seconds * 1000) + first; // get time 10 seconds ahead of the first
			int count = 0;

			// while the first time is not equal to the second, assign first to the current time
			while(first < second){

				if((second - first) == 1000 && displayStatus){
					System.out.println( "Second: " + (++count));
				}

				first = System.currentTimeMillis();
			}
	}

	private class Error242 extends Exception{
		public Error242(String arg){
			super(arg);
		}

		public Error242(){
			super("An error occurred with the specified request!\nPlease try again!");
		}
	}

	public void optionSelected(String str){

		// A new thread should only execute after the previous is finished--
		if(currentFuture == null){ // first test, but not thread safe - when it isn't null threads will skip this
			synchronized(lockObject){ // locks all threads, but one, out of the statement
				if(currentFuture == null){ // the single thread checks to see if currentFuture is null
					try{ 
						currentFuture = es.submit(new Request(str)); // single thread attempts this task
					}catch(Exception e){
						System.out.println(e);
					}
				}
			} // single thread has exited statement, releasing the lock and allowing a different thread to enter
		}else System.out.println("There is currently a task in process... please wait.");
	}

	private class Request implements Runnable{

		private URL userRequest = null;

		public Request(String userURL) throws Error242{
			try{
				userRequest = new URL(userURL);
			}catch(MalformedURLException me){
				// send error to some log for statistical reasons...
				throw new Error242(); // a more user-friendly error
			}
		}

		@Override public void run(){
			// task specific to SEL
			// task to be performed based on the user's request

			// dummy task to test the logic--
			ConcurrentExample.advance(5, true); // loudly wait 5 seconds
			// finally set the currentFuture to be null when the process is finished--
			currentFuture = null;
		}
	}
}

-- you could also lock upon the actual class that is being used by using synchronized(this), though I'm not entirely sure if this is recommended (for example, if an enclosing class of this class is using threads that lock on this object, does that mean there is extra indirection between threads monitoring the state of this object?). In addition, you can lock upon Singletons (or more generally, static instances) by using the qualified name with the .class extension.

Above I mention the volatile keyword, though I'm still not entirely sure I understand the concept of it between Java and C/C++. In C++ it is used as a signal the compiler that a particular chunk of code that performs operations on a particular member should not be optimized into a constant expression (which, I believe has more significance in Device Driver work). In Java, I believe it is used to determine if a particular instance/variable has been initialized properly (between Threads), though again I'm not 100% sure as the use of volatile is very elusive and very specialized.

Edit: Although the static function advance may not be considered Thread safe (due to the fact that multiple threads are accessing a potentially unsynchronized method of class System, and the fact that no threads are locking upon System.class), the members created from calling the function, and the intent of getting the current time of the system makes the function 'synchronized enough.' If you wanted to be completely correct, you'd have to lock on the System class which may not be preferable and may cause an IllegalMonitorState exception if you attempted to use System variables when a Thread has the lock on the System object.

Can you suggest some easy reading on concurrency (I like reading in style of Deitel or OReilly books, explanation with plenty of examples to try out)

Well I don't know if this would be an overkill (especially if you just need to start up) but when it comes to concurrency, I liked Java Concurrency in Practice By Brian Goetz

commented: Indeed, a very good book. +4

OK guys, it is working!
Current state of JSR-135: Mobile Media API still need lot of work. The main problem was I couldn't get PlayerListener working correctly to tell me when the song ends with (Player.END_OF_MEDIA) so I could supply another InputStream at that point to play.
Therefore I started to play around with threads and come to ask for help. I went ahead with Ezzaral solution and implemented into my application, however it was still giving me same result (little of first file over played by second). On the end I decided to read duration of song (Player.getDuration()) which returns long. However this long is not compatible with time in milliseconds. By pure luck I tried to divide by thousand and it seems to return correct number to use with Thread.sleep() method.
Looking at current state I think whole threads structure is not necessary and sleep method can handle all :D.

Thank you for your time and help, I really appropriate it.

Well I don't know if this would be an overkill (especially if you just need to start up) but when it comes to concurrency, I liked Java Concurrency in Practice By Brian Goetz

Yes, Java Concurrency in Practice would be my suggestion as well for thorough coverage of concurrency.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.