Better way to implement empty while loop to hold control - java

I am playing audio in background and I want the control of program to stay stand still till the audio playing is over for that I am using empty while loop as follows
while(isPlaying==true){};
mediaPlayer.stop();
as you can see while loop holds program control till audio is playing and after that next instruction is executed. This is working fine but I came to know that this is not a proper way to do this empty-while is expensive I am searching for alternative. Please Help.

Assuming your program is in Java (...why did you give it three language tags?) You have a few options. You could use a proper synchronization event, e.g.:
// fields
Object playerStopEvent = new Object();
boolean isPlaying;
// in your media player, when playback is complete:
synchronized (playerStopEvent) {
isPlaying = false;
playerStopEvent.notifyAll();
}
// elsewhere, when waiting for playback to complete:
synchronized (playerStopEvent) {
while (isPlaying) {
try {
playerStopEvent.wait();
} catch (InterruptedException x) {
// abort or ignore, up to you
}
}
}
mediaPlayer.stop();
See the official tutorial on Guarded Blocks for more examples.
You could also just have mediaPlayer call some callback when it is finished, and e.g. disable GUI components when you start playing and re-enable them when the finished callback is called (you could also use an event listener approach here).
Without more info, I recommend the latter, as it won't prevent you from doing other unrelated things (or keep your program from responding at all) while the player is playing, but the former may be more appropriate depending on your situation.
If it's in C or C++ the concept is the same. Use whatever equivalent of condition variables / events you have for the first option, or whatever equivalent of callbacks / listeners / signals+slots you have for the second.

well, in my humble opinion, it's better to use another implementation..
try to use thread so that it won't hang your program in there (it's a background audio afterall; you might want to do something else while the audio is playing)..
try to check this page out..

First thing is that you don't have to compare 2 Boolean fields that you have done in your code...
while(isPlaying==true){};
you can do so like..
while(isPlaying){};
and, now that you have told that you are using java, you can try this...
while(isPlaying){
Thread.sleep(1);
};

You may consider a sleep(time in milliseconds ). This will allow your thread executing while loop to sleep for specified milliseconds and then check the condition again.
while(isPlaying==true)
{
Thread.currentThread().sleep(1000); // sleep for 1 sec
};
This once is quick but the better way is to use some wait() and notify() mechanism as suggested by #JasonC in his answer.

You really don't need the {} in your empty while loop.
while(isPlaying); would suffice.
Also, as others have already suggested, consider using a delay inside your loop, i.e.
Thread.sleep(100); // sleeps for 1/10 of a seconds in Java
Or
delay(100); // leeps for 1/10 of a seconds in Java

The simple way is that put sleep(1) in while loop. And cpu usage won't take more.

Related

Wait for object to finish moving, then do action

I'm wondering if there is any built in way in Java to wait until something is finished, then keep going in the code.
In my case, I move an object from x to destinationX by 50px per frame when I press the object. To wait for that movement to finish before I keep going in my code I use a Timer atm, but I'm worried that might not be the best solution if someone runs on low fps.
Is there any way to do this without using a bunch of flags or a Timer? I looked into Events but can't find decent instructions on how I could apply it in my case.
You could work with states (= an integer) and change states once a condition is met, like
if(state == 1) moveObject();
if(state == 2) keepGoing();
and you change state from 1 to 2 once you reached the destination in moveObject();.
You can perform your actions in different threads and use Thread.join() as described here.

long running application (tail like)

I want to write an tail like app. Now this app, scans a file for changes in the background and fires events in case something changed.
I want to run my application until the user requests to exit it by pressing ctrl + c (working by default). I do not want to create a lot of CPU load just by doing an endless while(true) loop like I'm doing ATM:
try {
// thread doing the monitoring
thread.start();
// forcing the programm not to exit
while (System.in.available() == 0) {
Thread.sleep(5000);
}
} catch (final IOException e) {
e.printStackTrace();
}
Does anyone know a more elegant/the right approach for this?
I'm not sure why you are using a thread in the first place, the 'tail' unix script is simply a while(true) loop with no exit condition. It watches the file and prints changes if any is detected. I think by default it pauses 1 second, so basically:
while(true) {
// Code goes here. Watch file, System.out.print if it changes
Thread.sleep(1000);
}
No need for a thread. But to answer the question about the best way to keep your app alive: Simply don't return from the thread's run() method. You don't have to join the thread, the application will stay in the foreground as long as it has one non-daemon running thread.
If you want to read the System.in without busy-waiting, that's very easy to achieve. InputStream has blocking semantics so all you need to to is call one of the read methods and it will block until there is input available. If you are scanning text input, I'd advise BufferedReader.readLine. Also, do that on the main thread, no point in starting another one.

How to implement something like Try to get a value, if null then sleep a little without using Thread.sleep?

At one point in my application, I need to ask a cache (a HashMap, i.e.) for a value. If the value does not exist, I need to wait a little and try again. At the moment, this is implemented like this:
String result = cache.get(key);
for (int i = 0; result == null; i++) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
}
result = cache.get(key);
}
While it works, I have a feeling that using Thread.sleep is kinda false. Does the JDK provide anything for this sort of task? I thought about using an ScheduledExecutorService, but the thing is that it has to run in the main thread.
I would argue that your design is fundamentally problematic. Locking and memory visibility issues notwithstanding, you are essentially polling for an event using high level code. This is neither efficient nor very responsive w.r.t. latency.
You should switch to a more event-driven approach. At the very least, use an object monitor or a lock to wait for that value to be set, rather than polling.
Even better, use a message bus to register handlers and process events as they come - you can easily construct a multithreaded message bus using any BlockingQueue implementation to pass message objects.
Try using the BlockingQueue as a cache.
I don't think there is anyway around Thread.sleep if you really have to execute on the main thread.
Other possibility is using Object.wait(). It is almost like Thread.sleep() for you but supports interrupting by calling notify() on the same monitor.
Other possibility for you is to user java.util.Timer= (as was already mentioned by #Hovercraft Full Of Eels)
You could use a self populating cache(guava LoadingCache), so the get(...) will block until the data is fetched.
Combine it with a ExecutorService -> Future#get(long timeout, TimeUnit unit) And you could have timeouts too.
Hope i pointed you into the right direction :)

Using methods inside loops, Java and Android

I'm working on a Java class in an Android project that summarizes array entries saved in previous classes, with each entry itself being an array with multiple elements.
I've have created methods to move forwards and backwards through the entries, but given there can be over 100 entries I would like to create another method that cycles through them instead of pressing the "Next" button over and over again.
Is there a way to do this?
I've found that loops will only show the last entry, but below is the best example I can think of, of what I need.
for (int i = Selection; i<=Qty; i++){
Num.setText(Integer.toString(i));
loadNext();
try{
Thread.sleep(1500);
}catch(InterruptedException e){}
if (Brk=true){
break;
}
}
The solution that would be closest to your original answer would be to create a background thread that does the loop, loading each item inside an Activity.runOnUiThread(). You can also do a similar thing with AsyncTask and progress updates. See this article for more information on both of these:
http://developer.android.com/resources/articles/painless-threading.html
However, a better solution is to not have a loop at all - just have a timer, and increment your loop variable each time the timer runs.
It may work. However, it will cause your UI to freeze during each time you call the sleep method. In general, when you are dealing with UI stuff, never use Thread class. Instead, use the Handler class. There are a lot of documentation but if, after you have search exhaustively, you can't find a good example just let me know.
Your break condition seems wrong, and causes the loop breaks at the first iteration:
if (Brk=true){
break;
}
Brk=true is an assigment exception, not a comparation exception. It will return always true. The expresion should be Brk==trueto check if the variable value is true. But again, it is a boolean variable, so you don't need to compare, but just reference it at the if statement:
if (Brk){
break;
}

Java while loop and Threads! [duplicate]

This question already has answers here:
How can I abort a running JDBC transaction?
(4 answers)
Closed 5 years ago.
I have a program that continually polls the database for change in value of some field. It runs in the background and currently uses a while(true) and a sleep() method to set the interval. I am wondering if this is a good practice? And, what could be a more efficient way to implement this? The program is meant to run at all times.
Consequently, the only way to stop the program is by issuing a kill on the process ID. The program could be in the middle of a JDBC call. How could I go about terminating it more gracefully? I understand that the best option would be to devise some kind of exit strategy by using a flag that will be periodically checked by the thread. But, I am unable to think of a way/condition of changing the value of this flag. Any ideas?
I am wondering if this is a good practice?
No. It's not good. Sometimes, it's all you've got, but it's not good.
And, what could be a more efficient way to implement this?
How do things get into the database in the first place?
The best change is to fix programs that insert/update the database to make requests which go to the database and to your program. A JMS topic is good for this kind of thing.
The next best change is to add a trigger to the database to enqueue each insert/update event into a queue. The queue could feed a JMS topic (or queue) for processing by your program.
The fall-back plan is your polling loop.
Your polling loop, however, should not trivially do work. It should drop a message into a queue for some other JDBC process to work on. A termination request is another message that can be dropped into the JMS queue. When your program gets the termination message, it absolutely must be finished with the prior JDBC request and can stop gracefully.
Before doing any of this, look at ESB solutions. Sun's JCAPS or TIBCO already have this. An open source ESB like Mulesource or Jitterbit may already have this functionality already built and tested.
This is really too big an issue to answer completely in this format. Do yourself a favour and go buy Java Concurrency in Practice. There is no better resource for concurrency on the Java 5+ platform out there. There are whole chapters devoted to this subject.
On the subject of killing your process during a JDBC call, that should be fine. I believe there are issues with interrupting a JDBC call (in that you can't?) but that's a different issue.
As others have said, the fact that you have to poll is probably indicative of a deeper problem with the design of your system... but sometimes that's the way it goes, so...
If you'd like to handle "killing" the process a little more gracefully, you could install a shutdown hook which is called when you hit Ctrl+C:
volatile boolean stop = false;
Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
public void run() {
stop = true;
}
});
then periodically check the stop variable.
A more elegant solution is to wait on an event:
boolean stop = false;
final Object event = new Object();
Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
public void run() {
synchronized(event) {
stop = true;
event.notifyAll();
}
}
});
// ... and in your polling loop ...
synchronized(event) {
while(!stop) {
// ... do JDBC access ...
try {
// Wait 30 seconds, but break out as soon as the event is fired.
event.wait(30000);
}
catch(InterruptedException e) {
// Log a message and exit. Never ignore interrupted exception.
break;
}
}
}
Or something like that.
Note that a Timer (or similar) would be better in that you could at least reuse it and let it do with all of the details of sleeping, scheduling, exception handling, etc...
There are many reasons your app could die. Don't focus on just the one.
If it's even theoretically possible for your JDBC work to leave things in a half-correct state, then you have a bug you should fix. All of your DB work should be in a transaction. It should go or not go.
This is Java. Move your processing to a second thread. Now you can
Read from stdin in a loop. If someone types "QUIT", set the while flag to false and exit.
Create a AWT or Swing frame with a STOP button.
Pretend you are a Unix daemon and create a server socket. Wait for someone to open the socket and send "QUIT". (This has the added bonus that you can change the sleep to a select with timeout.)
There must be hundreds of variants on this.
Set up a signal handler for SIGTERM that sets a flag telling your loop to exit its next time through.
Regarding the question "The program could be in the middle of a JDBC call. How could I go about terminating it more gracefully?" - see How can I abort a running jdbc transaction?
Note that using a poll with sleep() is rarely the correct solution - implemented improperly, it can end up hogging CPU resources (the JVM thread-scheduler ends up spending inordinate amount of time sleeping and waking up the thread).
I‘ve created a Service class in my current company’s utility library for these kinds of problems:
public class Service implements Runnable {
private boolean shouldStop = false;
public synchronized stop() {
shouldStop = true;
notify();
}
private synchronized shouldStop() {
return shouldStop;
}
public void run() {
setUp();
while (!shouldStop()) {
doStuff();
sleep(60 * 1000);
}
}
private synchronized sleep(long delay) {
try {
wait(delay);
} catch (InterruptedException ie1) {
/* ignore. */
}
}
}
Of course this is far from complete but you should get the gist. This will enable you to simply call the stop() method when you want the program to stop and it will exit cleanly.
If that's your application and you can modify it, you can:
Make it read a file
Read for the value of a flag.
When you want to kill it, you just modify the file and the application will exit gracefully.
Not need to work it that harder that that.
You could make the field a compound value that includes (conceptually) a process-ID and a timestamp. [Better yet, use two or more fields.] Start a thread in the process that owns access to the field, and have it loop, sleeping and updating the timestamp. Then a polling process that is waiting to own access to the field can observe that the timestamp has not updated in some time T (which is much greater than the time of the updating loop's sleep interval) and assume that the previously-owning process has died.
But this is still prone to failure.
In other languages, I always try to use flock() calls to synchronize on a file. Not sure what the Java equivalent is. Get real concurrency if you at all possibly can.
I'm surprised nobody mentioned the interrupt mechanism implemented in Java. It's supposed to be a solution to the problem of stopping a thread. All other solutions have at least one flaw, that's why this mechanism is needed to be implemented in the Java concurrency library.
You can stop a thread by sending it an interrupt() message, but there are others ways that threads get interrupted. When this happens an InterruptedException is thrown. That's why you have to handle it when calling sleep() for example. That's where you can do cleanup and end gracefully, like closing the database connection.
Java9 has another "potential" answer to this: Thread.onSpinWait():
Indicates that the caller is momentarily unable to progress, until the occurrence of one or more actions on the part of other activities. By invoking this method within each iteration of a spin-wait loop construct, the calling thread indicates to the runtime that it is busy-waiting. The runtime may take action to improve the performance of invoking spin-wait loop constructions.
See JEP 285 for more details.
I think you should poll it with timertask instead.
My computer is running a while loop 1075566 times in 10 seconds.
Thats 107557 times in one second.
How often is it truly needed to poll it? A TimerTask runs at its fastest 1000 times in 1 second. You give it a parameter in int (miliseconds) as parameters. If you are content with that - that means you strain your cpu 108 times less with that task.
If you would be happy with polling once each second that is (108 * 1000). 108 000 times less straining. That also mean that you could check 108 000 values with the same cpu strain that you had with your one while loop - beause the you dont assign your cpu to check as often. Remember the cpu has a clock cycle. Mine is 3 600 000 000 hertz (cycles per second).
If your goal is to have it updated for a user - you can run a check each time the user logs in (or manually let him ask for an update) - that would practically not strain the cpu whatsoever.
You can also use thread.sleep(miliseconds); to lower the strain of your polling thread (as it wont be polling as often) you where doing.

Categories

Resources