Edit, found a work around, code is posted at the bottom.
Is it possible to pause a thread that's in the middle of using thread.sleep(sleeptime)? And then when it's resumed, sleep for the remaining time?
I tried implementing the wait/notify set up here to pause a thread
How to pause/resume thread in Android?
However, it looks like it waits until thread.sleep is finished with it's sleeping time.
The reason why I am asking this because I am using a while loop inside a thread to play music from a play list, and I need the thread to sleep for the duration of the music track so that the music track finishes before the while loop plays the next song on the playlist.
For example, the while loop will play a song that has a duration of 50 seconds, so the thread.sleep method will pause the thread that contains the while loop. But, the user wants to the pause the song, and the whole play list 25 seconds into the song. So the user will press the pause button 25 seconds into thread.sleep's 50 second sleep. After the user unpauses, I would like the thread.sleep to continue the rest of 50 second wait (25 seconds left at this point) to complete playing the rest of the song. Then the while loop will play the next track on the playlist.
Runnable whilePlay2 = new Runnable() {
#Override
public void run(){
while (k <= myIntArray2.size()-1 ) {
System.gc();
if( myIntArray2.get(k)>count){
video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
videocursor.moveToPosition(myIntArray2.get(k)-count);
filename2 = videocursor.getString(video_column_index);
}
else{
music_column_index = musiccursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
musiccursor.moveToPosition(myIntArray2.get(k));
filename2 = musiccursor.getString(music_column_index);
}
try {
if (m2MediaPlayer.isPlaying()) {
m2MediaPlayer.reset();
}
m2MediaPlayer.setDataSource(filename2);
m2MediaPlayer.prepare();
m2MediaPlayer.start();
Thread.sleep(m2MediaPlayer.getDuration());
synchronized(Lock){
while(onS){
Log.i("should be", "waiting");
Lock.wait();
}
}
Log.i("what is on", "on is"+onS);
Log.i("k Check", "k is" +k);
} catch (Exception e) {
}
m2MediaPlayer.stop();
m2MediaPlayer.reset();
k++;
}
} //closes public void run(){
// TODO Auto-generated method stub
};
Thread whilePlay2T = new Thread(whilePlay2);
whilePlay2T.start();
And here is my pause button
public void onToggleClicked(View view) {
// Is the toggle on?
boolean on = ((ToggleButton) view).isChecked();
if (on) {
mMediaPlayer.pause();
length=mMediaPlayer.getCurrentPosition();
m2MediaPlayer.pause();
length2=m2MediaPlayer.getCurrentPosition();
synchronized (Lock){
onS=true;
}
} else {
mMediaPlayer.seekTo(length);
mMediaPlayer.start();
m2MediaPlayer.seekTo(length2);
m2MediaPlayer.start();
synchronized (Lock){
onS=false;
Lock.notifyAll();
}
}
}
EDIT
Looks like I can't use it. So now I am using a recursive function instead of a while loop to set up my play list. Here's what one of them looks like.
public void hiplaylist2(int t2) {
k=t2;
if(k <= myIntArray2.size()-1 ){
System.gc();
if( myIntArray2.get(k)>count){
video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
videocursor.moveToPosition(myIntArray2.get(k)-count);
filename2 = videocursor.getString(video_column_index);
}
else{
music_column_index = musiccursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
musiccursor.moveToPosition(myIntArray2.get(k));
filename2 = musiccursor.getString(music_column_index);
}
try {
if (m2MediaPlayer.isPlaying()) {
m2MediaPlayer.reset();
}
m2MediaPlayer.setDataSource(filename2);
m2MediaPlayer.prepare();
m2MediaPlayer.start();
//Thread.sleep(mMediaPlayer.getDuration());
//SystemClock.sleep(mMediaPlayer.getDuration());
Log.i("k Check", "k is" + k);
} catch (Exception e) {
}
}
m2MediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
public void onCompletion(MediaPlayer m2MediaPlayer){
m2MediaPlayer.stop();
m2MediaPlayer.reset();
if(k < myIntArray2.size()-1 ){
k++;
hiplaylist2(k);
}
}
});
};
And then I ues a thread to have more than one of these run at the same time.
I don't really get it. I'm not sure about what you want to do, but i guess that there are at least two problems into your algorithm.
Firstly, when you work on concurrent tasks take care of your race conditions, your m2MediaPlayer seems to be one of them.
Concerning your Thread.sleep(m2MediaPlayer.getDuration()); I believe that you shouldn't do it this way, if you want to wait until your song is finished you just have to :
Launch your song from Thread 1
Pause your Thread 1 (wait)
The song is playing in Thread 2
When the song is finished wake up (notify) your Thread 1 from Thread 2 (and let T2 die)
Note that you have to keep your code as simple as you can, because concurrency is hell.
Is it possible to pause a thread that's in the middle of using thread.sleep(sleeptime)? And then when it's resumed, sleep for the remaining time?
Assuming that you are asking about the behaviour of the Java runtime libraries, then the answer is No.
There is no safe way to pause and resume a thread. The Thread suspend / resume methods for doing this are unsafe and were deprecated in Java 1.1. (Read this if you want an explanation.)
Even if you use the unsafe methods, they do not magically pause a sleep timer. In fact, it is not clear what would happen to a sleeping thread: it is not specified.
Indeed, I would not totally be surprised if you found that a sleeping thread whose sleep time expired while suspended never woke up ...
I'll leave it to others to deal with the rest of your question.
(I can't figure out from your description what it is you are trying to do here ... and why you even need to pause a sleeping thread. On the face of it, it sounds like you should be using wait / notify or a higher level synchronization class ... rather than sleeping. The fact that you apparently tried and failed does not make that the wrong solution.)
Related
I do not understand the behaviour of my code. To summarize, I have an editText (variable hours in my code) that start with "00". I am creating a thread which prevents this editText to not have 2 digit. Let s assume that this editText cannot have more than 2 digits. What I am doing is that I create a thread. In this thread, whenever this editText does not have 2 digits(so 1 digit), I add to it a "0".
However, whenever I just put one digit on the editText, it is getting crazy and go into an infinite loop and other stuff that I don't understand. Here is my code:
Thread digitLessThanTwoThread;
EditText hours = (EditText) findViewById(R.id.hours);
digitLessThanTwoThread= new Thread(){
#Override
public void run()
{
while(true) {
if (hours.getText().toString().length() != 2 && !hours.isFocused()) {
main_activity.runOnUiThread(new Runnable() {
#Override
public void run() {
hours.setText("0" + hours.getText().toString());
}
});
}
}
}
};
digitLessThanTwoThread.start();
Moreover, at the end, The editText hours displayed "00".
I also get a message "suspending all threads took: XXX seconds" before doing anything actually!
There are two problems here. First, the simple one:
while(true)
This will run the thread at full power until as you seem to be noticing, the OS steps in to stop the runaway thread. You should instead add an addTextChangedListener() listener, for example.
The more complex one is:
main_activity.runOnUiThread(new Runnable() {
#Override
public void run() {
hours.setText("0" + hours.getText().toString());
}
});
I think you are assuming that this is executed synchronously, that is the setText() is executed before runOnUiThread() returns. However, it is asynchronous, so next time round the loop your if is still true, and you queue another action on the UI thread to set the text and so on, so the UI thread may never get a chance to run until the OS steps in to halt the runaway thread.
I have two threads in my ChessGame and I want to implement time control:
Turn of first player: second_thread.stop(), first_thread.run();
counterOfSteps++;
Turn of second player: first_thread.stop(), second_thread.run();
counterOfSteps++;
I have founded many information about Timer but I need Threads.Second thread the same.
There is my code of first thread and it doesn't work because time isn't stopped (System.currentTimeMillis)
first = new Thread() {
#Override
public void run() {
final long time = System.currentTimeMillis();
final long duration = 10800000; //3 hours
while (true) {
try {
Thread.sleep(100);
if (counterOfSteps % 2 == 0) {
System.out.println("Time" + ((duration - (System.currentTimeMillis() - time)) / 1000) % 60);
}
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, "Unexpected interrupt", ex);
}
}
}
};
How to solve this problem?
Update:
I don't use .stop(). I wrote is for example how to realize.
I have founded many information about Timer but I need Threads.
No. If all you are trying to do is implement a chess clock, then you don't need threads for that. A Timer task that wakes up every second (or every 1/10 second) can;
look at whose turn it is (e.g., counterOfSteps % 2),
compute how much time that player has used, and
Update the appropriate text box in the GUI.
To compute how much time, it'll need to know three things;
What time it is now (e.g., System.currentTimeMillis()),
What time it was when the current turn started, and
How much time the player already had on the clock when the current turn started.
There is no way to pause the system clock (i.e., System.currentTimeMillis()), but that's not a problem. If you sample the clock at the start of each turn, then you can compute the duration of the current turn as System.currentTimeMillis() minus the start time.
I used this example for my quiz, i have 10sec do answer on question this timer decrease int t every 1sec, and set how many times left in some JLabel. You can make 2 object of Timer, first object for first player and second object for second player. You can stop timer when someone finish the move and start second timer...
int t=10
lb2=new JLabel(t);
tim=new Timer(1000,new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(t>0){
t--;
lb2.setText(String.valueOf(t));
}else{
tim.stop();
JOptionPane.showMessageDialog(null, "Time is up");
}
}
});
}
I am using a Canvas in a SurfaceView Class which runs on a thread. The SurfaceView is called by an Activity (setContentView(surfaceview)). When the screen turns off, it goes through a pause() method which turns off all loop variables and so on.
The strange thing is: while on my tablet (Android 4.4.2) the Thread pauses and resumes correctly (the thread starts all over), however on my phone (Android 4.2.2) and on other people's phone (CM 11) the app hangs (it doesn't crash! it just hangs) and I have to kill it. LogCat doesn't print anything - however I tried to find out what happens using Log.i, it seems that after the pause method finishes, the pause method starts again, and this is where the app hangs.
I have checked before and the pause/resume methods are getting called correctly (override of onPause/onResume of the Activity using super.onPause()/Resume() and then surfaceview.pause()/resume())
My pause/resume methods:
public void resume() {
countdown = true; // this one,
threadRun = true; // this one and
finishWait = true; // this one each are loop controllers
won = false;
hitCount = 0;
thread = new Thread(this);
thread.start();
}
public void pause() {
Log.i("codeflow", "Pause method start");
// all loop controllers have been set to false
countdown = false;
threadRun = false;
finishWait = false;
/* Log.i("CodeFlow", "drawablank");
drawABlankScreen(); // to hide everything drawn */
while (true) {
try {
Log.i("codeflow", "Thread.join() loop");
thread.join();
break;
} catch(InterruptedException e) {
Log.i("codeflow", "InterruptedException");
e.printStackTrace();
}
}
thread = null;
Log.i("codeflow", "Thread is killed");
if (won && !lost) { // !lost IS necessary
Log.i("CodeFlow", "save highscore");
saveHighscore(highscore);
}
}
The pause method goes through everything the way it should, but then it starts again (another "Pause method start") and goes either to drawABlankScreen() or, when this linke is commented, it prints "Thread.join() loop" once and then the app hangs.
The thing that bugs me the most it that it hangs on my phone while it doesn't hang on my tablet.
Can anyone please help me, I've searched for hours and found nothing....
Joining the UI thread to a background thread in onPause() is probably what's causing your problem.
Instead, you should kill the thread.
"thread.join()" will hangs the thread which execute this sentence, until thread run over. Strangly, if execute in Android UI thread, Android would not crash.(sorry for my full of mistakes English).
I have a program that rolls dice, and uses a new thread to loop through in order to update the image and repaint. Here is my code:
public int roll()
{
new Thread(
new Runnable() {
public void run() {
synchronized(o) {
o.notify();
for (int i = 0; i < 10; i++) {
image = randomImage();
repaint();
try {
Thread.sleep(100);
}
catch(InterruptedException ex) {
System.out.println("InterruptedException caught");
}
}
}
}
}
).start();
synchronized(o) {
try {
o.wait();
}
catch(InterruptedException ex) {
System.out.println("InterruptedException caught");
}
}
return rolled;
}
In my other class, I have:
int rolled = dicePanel.roll();
label.setText("Rolled a + rolled");
The problem is that with the current code with synchronization, the dice images do not animate, but do return the correct int rolled. Without the synchronized code, the images will animate but the roll method will return a 0 as the int because it does not let the other thread finish.
Is there any way to have the image code loop through and repaint each time, but wait until the thread has finished to return the int rolled?
This looks like an overly complicated solution. You should certainly perform your dice rolling / image updating in thread other than the EDT, but you needn't split that task into two separate threads.
Just have one thread that fiddles with your dice images then when it's finished doing that, it can set the chosen dice value in your label (and presumably in your image too).
Put the o.notify(); to the end of the run() method. Btw. using notifyAll() should be preferred. Or you may find useful the Future object pattern. Here is an article about it http://www.vogella.com/articles/JavaConcurrency/article.html
Or if you are developing Swing application look to SwingWorker. However, SwingWorker is probably overkill for this task.
Wait¬ify is quite low level api and there are many good abstraction in Java to work with concurrency.
I am trying to stop a for loop that is initiated by pressing a button. The only problem I have found is that the application is literally non-responsive once the start button is pressed. How would I go about making the stop button? At the moment the only way I can stop the application outside of my IDE is to go into task manager and forcibly delete it.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String L = "Hello";
int Num = Integer.parseInt(m1.getText());
int Num2 = Integer.parseInt(m2.getText());
nu = Num;
for (int kk = nu; nu > 0; nu--) {
if (O1.isSelected()) {
for (int num3 = nu; nu > 0; nu--) {
try {
try {
Thread.sleep(Num2 * 1000);
} catch (InterruptedException ex) {}
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_F);
} catch (AWTException e) {
e.printStackTrace();
}
}
}
}
This is the code I have, I have been looking around and I think I need to use the SwingWorker class. I am not sure how to implement it though.
Have you put your loop inside the button action handler?
If so remove it and put it in a thread. Else it will block the EDT and app will become unresponsive. Use buttons only to trigger start and stop.
Without code it is hard to determine, but you are probably performing the loop on AWT thread, hence your UI is blocked and you can not press a button.
You should move your endless loop to another Thread, and then the button will work
You are entering in an infinite loop any how. I would suggest to put your loop in a separate thread and when you want to stop it just interrupt that thread on button click.
Move the code into a dedicated thread and use a variable check to end the loop externally.
The first problem is that you're performing this loop inside the Event Dispatch Thread (EDT). This is a thread which is dedicated to handling the user interface. Since you are looping and sleeping in this thread, it is unavailable to handle any other user interactions. So effectively you are locking yourself out of your own program.
The proper way to shut this down is to create a shutdown() method on the loop which will modify a variable that is checked in each iteration of the loop. Then, when you want to shut it down, you just call this method on the Runnable and the loop shuts down.
public class KeyPressRunnable implements Runnable {
private boolean isRunning = true;
public void shutdown() {
this.isRunning = false;
}
#Override
public void run() {
// put your loop in here, and include this code in the loop:
if (!this.isRunning) break;
}
}