Inconsistent sleep behavior when using AudioClip in Java - java

I am writing Ukelele Simulator, and I want to play a note on each string with a short delay in between. Currently, I have a method that returns an AudioClip containing the sound of the currently pressed note on each string, and I am attempting to play those AudioClips in succession with a 500 millisecond delay using Thread.sleep().
public static void main(String[] args){
//test it
UkeString stringG = new UkeString('G');
UkeString stringC = new UkeString('C');
UkeString stringE = new UkeString('E');
UkeString stringA = new UkeString('A');
try{
AudioClip G = stringG.getNoteAudio();
AudioClip C = stringC.getNoteAudio();
AudioClip E = stringE.getNoteAudio();
AudioClip A = stringA.getNoteAudio();
G.play();
Thread.sleep(500);
C.play();
Thread.sleep(500);
E.play();
Thread.sleep(500);
A.play();
Thread.sleep(500);
}
catch(Exception e){
System.out.println(e);
}
return;
}
However, I am encountering some odd irregular behavior from Thread.sleep(). Normally, when I execute the above code the first Thread.sleep() following G.play() either does not execute for the full 500 milliseconds or not at all, because the 'G' and 'C' notes are played in rapid succession. After that, the 'E' and 'A' notes will play as expected in 500 millisecond intervals.
The really weird thing is that if I run the program again before the other instance has ended (i.e. the notes in the old instance are still playing), then the new instance executes as expected with all the notes playing in 500 millisecond intervals. What's going on here?

See http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
Your answer is here (in bold):
Causes the currently executing thread to sleep (temporarily cease
execution) for the specified number of milliseconds, subject to the
precision and accuracy of system timers and schedulers.
In other words, you can't have that much of a fine control with time using Thread.sleep()

Related

How can I properly block a thread until timeout starts?

I would like to run several tasks in parallel until a certain amount of time has passed. Let us suppose those threads are CPU-heavy and/or may block indefinitely. After the timeout, the threads should be interrupted immediately, and the main thread should continue execution regardless of unfinished or still running tasks.
I've seen a lot of questions asking this, and the answers were always similar, often along the lines of "create thread pool for tasks, start it, join it on timeout"
The problem is between the "start" and "join" parts. As soon as the pool is allowed to run, it may grab CPU and the timeout will not even start until I get it back.
I have tried Executor.invokeAll, and found that it did not fully meet the requirements. Example:
long dt = System.nanoTime ();
ExecutorService pool = Executors.newFixedThreadPool (4);
List <Callable <String>> list = new ArrayList <> ();
for (int i = 0; i < 10; i++) {
list.add (new Callable <String> () {
#Override
public String call () throws Exception {
while (true) {
}
}
});
}
System.out.println ("Start at " + (System.nanoTime () - dt) / 1000000 + "ms");
try {
pool.invokeAll (list, 3000, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
}
System.out.println ("End at " + (System.nanoTime () - dt) / 1000000 + "ms");
Start at 1ms
End at 3028ms
This (27 ms delay) may not seem too bad, but an infinite loop is rather easy to break out of - the actual program experiences ten times more easily. My expectation is that a timeout request is met with very high accuracy even under heavy load (I'm thinking along the lines of a hardware interrupt, which should always work).
This is a major pain in my particular program, as it needs to heed certain timeouts rather accurately (for instance, around 100 ms, if possible better). However, starting the pool often takes as long as 400 ms until I get control back, pushing past the deadline.
I'm a bit confused why this problem is almost never mentioned. Most of the answers I have seen definitely suffer from this. I suppose it may be acceptable usually, but in my case it's not.
Is there a clean and tested way to go ahead with this issue?
Edited to add:
My program is involved with GC, even though not on a large scale. For testing purposes, I rewrote the above example and found that the results given are very inconsistent, but on average noticeably worse than before.
long dt = System.nanoTime ();
ExecutorService pool = Executors.newFixedThreadPool (40);
List <Callable <String>> list = new ArrayList <> ();
for (int i = 0; i < 10; i++) {
list.add (new Callable <String> () {
#Override
public String call () throws Exception {
String s = "";
while (true) {
s += Long.toString (System.nanoTime ());
if (s.length () > 1000000) {
s = "";
}
}
}
});
}
System.out.println ("Start at " + (System.nanoTime () - dt) / 1000000 + "ms");
try {
pool.invokeAll (list, 1000, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
}
System.out.println ("End at " + (System.nanoTime () - dt) / 1000000 + "ms");
Start at 1ms
End at 1189ms
invokeAll should work just fine. However, it is vital that you write your tasks to properly respond to interrupts. When catching InterruptedException, they should exit immediately. If your code is catching IOException, each such catch-block should be preceded with something like:
} catch (InterruptedIOException e) {
logger.log(Level.FINE, "Interrupted; exiting", e);
return;
}
If you are using Channels, you will want to handle ClosedByInterruptException the same way.
If you perform time-consuming operations that don't catch the above exceptions, you need to check Thread.interrupted() periodically. Obviously, checking more often is better, though there will be a point of diminishing returns. (Meaning, checking it after every single statement in your task probably isn't useful.)
if (Thread.interrupted()) {
logger.fine("Interrupted; exiting");
return;
}
In your example code, your Callable is not checking the interrupt status at all, so my guess is that it never exits. An interrupt does not actually stop a thread; it just signals the thread that it should terminate itself on its own terms.
Using the VM option -XX:+PrintGCDetails, I found that the GC runs more rarely, but with a far larger time delay than expected. That delay just so happens to coincide with the spikes I experienced.
A mundane and sad explanation for the observed behavior.

Why does my java TimerTask stop executing in Netbeans?

I am running a java application in a TimerTask using the schedule method, i.e. it runs at certain intervals and if the timertask gets delayed it does not try to play catch-up. I want the program to run for as long as possible if not indefinitely. I am using Netbeans 7.3.
However, I find that after a few hours (sometimes only 1 hour and sometimes over 24 hours) the program stops printing to the console and in fact stops running altogether. I know it isn't simply that it stops printing to the console because the program also sends an email regularly, and after it stops the emails stop coming as well. It does not always say "build complete" or throw an exception, though sometimes it will simply say "build complete" and stop running.
I have tried looking around the web, but I cannot seem to find any conclusive answer. I saw somewhere that the TimerTask will stop running if it throws an unchecked excpetion, but since it does not always stop at the end of a TimerTask but rather at some random point in the middle of a task, I don't think that is what's happening.
Does anyone have any idea what is going wrong and how I can work around it?
Any pointers would be much appreciated.
Thanks,
Paul
EDIT: after I tried putting a logger into my timertask, the code errored out with the following exception:
java.io.IOException: Couldn't get lock for Logging.txt. This may very well be a separate problem because I have never used a logger. I read somewhere that this exception probably means I am missing some permissions to write to the file in java (not sure if that is the case or how to fix in Netbeans). If I fix the logger it and it's unrelated I will delete this edit
EDIT: I forgot to mention that the Broadcast function involves a lot of communication with various servers. I think the problem might be that the program simply gets stuck on a line and never completes. In this case I need to figure out a way to have the broadcast method timeout after a certain amount of time and try again.
EDIT: here is an example of my code:
public void RUN(){
exchanges.add(Bitstamp);
exchanges.add(BTCE);
exchanges.add(CampBX);
t.schedule(
new TimerTask()
{
public void run()
{
Broadcast(exchanges);
UseLogger.Log();
}
}, 0,15000);
}
public static void Broadcast(ArrayList<Exchange> exchanges){
for (int i=0; i<exchanges.size();i++){
exchanges.get(i).prepareGetUpdate();
}
System.out.println("************** TICKERS *****************");
try{
for (int i=0; i<exchanges.size();i++){
System.out.println(exchanges.get(i).getPrices());
}
tickerException=false;
} catch (Exception e){
tickerException=true;
}
System.out.println("");
System.out.println("************** BALANCES *****************");
try{
for (int i=0;i<exchanges.size();i++){
System.out.println("i: " + i);
System.out.println(exchanges.get(i).getBalance());
}
balanceException=false;
} catch (Exception e){
balanceException=true;
}
System.out.println("************ ORDERS *****************");
try{
for (int i=0; i< exchanges.size();i++){
exchanges.get(i).getOrders();
if (exchanges.get(i).exchangeName.contentEquals("BTCE")){
exchanges.get(i).Total_btc+=exchanges.get(i).btcInOrders;
exchanges.get(i).Total_usd+=exchanges.get(i).usdInOrders;
}
}
orderException=false;
} catch (Exception e){
orderException = true;
}
for (int i=0; i< exchanges.size();i++){
exchanges.get(i).getUpdate();
}
btcDiff = totalBTC-originalTotal;
btcNeutral=true;
}

Android: Create a loop-able tone

I have been trying to generate a tone (444 hz, 1000 hz, etc) and then play it in Android. My first searches gave me this stack overflow question. While this works great given a duration, I would prefer to make the duration infinite (loop-able).
First I used only use integer values for the tone, because this would mean that I could use 1 second and it should loop properly. However there are still some frequencies that don't loop right.
Second I thought I could only calculate 1 period of the sine wave, and then loop that. However I found out that is not a viable approach
How can I, given any frequency, generate a tone that I can loop?
You can create a thread that will run your tone every period of time(for example 2sec.):
private Runnable startSoundRunnable = new Runnable() {
#Override
public void run() {
while (true) {
try {
toneGenerator.startTone(ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE, 2000);
sleep(2000);
} catch (Exception ex) {}
}
}
};
// Run thread
new Thread(startSoundRunnable).start();

Program not waiting for Timer to finish before continuing its loop

I have the following code that runs whenever you click the Start button on my program. I have denoted via comments where I want the timer to go, problem is, when I do thread.sleep(time) it freezes my program! So, I was wondering if someoen could just simply add atimer to my code so it runs the first bit, waits, then runs it again based on bumpNum.
Code:
public class startReplyButtonListener implements ActionListener{
public void actionPerformed(ActionEvent ev){
int length = textAreaReplyMessage.getText().length();
int remLen = 400 - length;
String strHTML = neo.get("http://www.neopets.com/neoboards/topic.phtml?topic=" + txtTopicID.getText());
/*strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
if(strHTML.contains("No topic with ID")){
txtLog.append("Invalid Topic ID! \n");
}
else{
txtLog.append("Bumped Topic ID " + txtTopicID.getText() + "\n");
}
*/
System.out.println(strHTML);
bumpNum = 5;
wait = Integer.parseInt(textWait1.getText()) * 1000; //converting to miliseconds
int i=1;
do{
strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
txtLog.append("Board Bumped. Waiting "+ ((Integer)(wait/1000)).toString() +" Seconds..." + "\n");
//ADD TIMER HERE
i++;
}while(i <= bumpNum);
}
}
What I wish to accomplish:
User indicates how many times they want to "post"(indicated by bumpNum), the loop will first, post once:
strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
Then:
Based on users input, it will wait for however many seconds(txtWait1) and THEN repeat the posting code above until it has reached bumpNum.
And it will update txtLog with the following EACH TIME it bumps(so the program cannot be frozen):
txtLog.append("Board Bumped. Waiting "+ ((Integer)(wait/1000)).toString() +" Seconds..." + "\n");
Edit:
Sigh. Ok, now I understand. I don't know the answer. You are talking about drawing a GUI element. I suspect you want to fork a thread to do a job and then show the GUI display that you are waiting for it. You need to wait for the thread to finish (see my join code below) all of the time having the GUI element refresh UNTIL it finishes when you display some result.
This depends more on the GUI code than sleep/timer. I would start a new question now and explain !!!NOT WITH CODE!!! but with pseudo code from 1000 foot view what you want. Something like:
I am trying to fork a thread that runs in the background in [Swing/Android/etc]. I want to display to the user that the thread has been forked, I want the user interface to wait for the thread without freezing, and then I want the user interface to join with the thread and display the results.
Think about the problem like we have to think of it. Anticipate questions that we will ask. Figure out what we don't and can't know about your environment.
Best of luck.
Edit:
If you are just trying to call sleep then you don't need to fork a thread for that. All you need to do in your code is:
try {
Thread.sleep(waitingTime);
System.out.println(waitingTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
This will pause the current thread (which could be the main thread) for waitingTime milliseconds.
So you are forking 3 threads very quickly which I guess you don't want to do. If you are trying to wait for each thread to finish then you will have to do something like:
Thread thread = new Thread(new Counter(wait));
thread.start();
thread.join();
Couple of other comments:
It is considered bad form to start a thread in the constructor of a class: new Thread(this).start();
You are creating 2 thread objects inside of your Runnable. You should just create one outside of your Runnable. See above.
Thread myCounter = new Thread(this); << #1
public Counter(int waitingTime) {
new Thread(this).start(); << #2
}
I would not initialize waitingTime = 0; when defined and initialize it in the constructor. This is confusing. Remove the = 0.
    int waitingTime; << remove the =0 here
    public Counter(int waitingTime) {
 this.waitingTime = waitingTime;
When you catch InterruptedException, be sure to handle it right. A good pattern is to reset the interrupt flag and/or quit the thread:
} catch (InterruptedException e) {
// resets the interrupt flag cleared by catching the exception
Thread.currentThread.interrupt();
// or stops the thread immediately
return;
}
You're starting a new thread each time through the loop. Rather than creating a new thread in the constructor, move the do/while loop into a normal method rather than the run method of a new thread. What you're doing is spawning a new thread that does in fact sleep, but it's not the thread that's executing the loop so that thread just continues as normal.

Taking input in Java without program hanging?

I was just wondering how i would let my java program continue running, but always be ready to take input.
Right now i am using a bufferreader and reading in a line, but that makes my program halt and wait for input. I want the program to continue running but be ready to take input whenever needed, is there a way to do this?
I would expect that you're going to have to look into multithreading your application in order to get this working as you desire.
Edit: Of course, while this functionality can be achieved by a purely CLI interface, you would probably be better off exploring other options (i.e. GUI options) if you intend on having a full response/event-driven system running in a multithreaded fashion.
Here is a quick example of how a multi-threaded command line interface application may work. This will not require polling for input, nor a GUI interface in order to perform tasks in the background while waiting for input from a user in a console.
In this example, a Thread is running in the background, which can be told to output a greeting in a specified number of seconds later.
public class CommandLineMultiThread
{
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
// Makes and runs the background thread.
MyThread myThread = new MyThread();
Thread t = new Thread(myThread);
t.start();
// Get the number of seconds to wait from the console.
// Exit when "0" is entered.
int waitDuration;
do
{
waitDuration = s.nextInt();
myThread.setGreetIn(waitDuration);
} while (waitDuration != 0);
myThread.quit();
}
static class MyThread implements Runnable
{
boolean running = true; // Boolean to keep thread alive.
long greetingTime = Long.MAX_VALUE; // Time to greet at.
public void setGreetIn(int i)
{
greetingTime = System.currentTimeMillis() + (i * 1000);
}
public void quit()
{
running = false;
}
public void run()
{
while (running)
{
if (System.currentTimeMillis() > greetingTime)
{
System.out.println("Hello!");
greetingTime = Long.MAX_VALUE;
}
try
{
Thread.sleep(100);
}
catch (InterruptedException e) {}
}
}
}
}
The Scanner class can be used to accept user input from the command line interface by routing the input from the System.in object.
Then, while the background thread myThread is running, the main thread is waiting for an input from System.in via the Scanner.nextInt method. Once the seconds to wait has been accepted, the background thread is told to wait until a certain time, and once that time arrives, the greeting Hello! is output to the console.
I think your program will have to occasionally poll for user input.
Give it a nice multi-threaded GUI instead of a CLI :)
I agree with James, another alternative is "faking" continuous program running. This won't work with all scenarios, but you can set a timer right before you display the user input, then calculate the time between stop and "start" again when the user inputs something.
Use that time to perform a repeated function a certain number of times. This is only helpful if you've got something on a timer itself already, like a constantly draining integer every few seconds.
An example:
You ask the user a question but only want to give them 5 seconds to answer. When the user answers (hits enter) the program will compute the time it took them to enter, if too long, throw one message, if under the time limit throw another.
I'm only suggesting this method because threading, which is what you really want to get into, is quite advanced.

Categories

Resources