Thread is blocking execution - java

I have a simple class which has a thread in it. Whenever user clicks on a button, I want to run the thread. Everything works great, except that whenever I click on the button while the thread is already running, my onTouch executes only after the thread has finished executing.
..
MyTouchAnimatorClass touchAnimatorClass = new MyTouchAnimatorClass();
view.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick( View view )
{
touchAnimatorClass.onTouch();
}
});
..
And my class with the thread:
Class MyTouchAnimatorClass
{
private boolean threadRunning = false;
public void onTouch() // <-- only executes AFTER the thread is complete
{
if( !threadRunning )
animate();
}
private void animate()
{
threadRunning = true;
Runnable r = new Runnable()
{
#Override
public void run()
{
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
int i=0;
boolean doBreak = false;
while( true )
{
i+=1;
if( i == 100 )
break;
}
}
}
}
}
new Thread( r ).start();
threadRunning = false;
}
}
I can't understand why this is happening, isn't the Runnable running in its own thread? Any suggestions please? Thank you!
EDIT:
I tried using
new Thread( r ).start();
Instead of:
r.run();
But unfortunately the same problem persists:
If I click the button the second time (while the thread is still running from the first click), it should execute onTouch, but shouldn't execute animate() since it is still running from the previous click.
What actually happens: The touch is non response until the thread from the first click has finished executing. Then onTouch triggers (even though I pressed it few seconds ago) and a new thread is started again.
If I press the button 10 times quickly, it will do 10 loops in a row, instead of doing one and blocking the others.

activity.runOnUiThread is asking the Android system to run this Runnable on the UI thread.
You can rather do new Thread(r).start();
Like this:
private void animate()
{
threadRunning = true;
//Define the work as a Runnable
Runnable r = new Runnable()
{
#Override
public void run()
{
int i=0;
//boolean doBreak = false; //Not used
while( true )
{
i+=1;
if( i == 100 )
break;
}
threadRunning = false; //Just before leaving
}
}
//Give that work to a new thread and start the thread
new Thread(r).run();
}

Runnable isn't a thread, is just a set of instructions to be executed in a thread
in order to achieve what you want you need to do
new Thread(r).start(); at end of your code

Related

How to pause a thread using wait and notify JavaFX

I am unclear on how to use wait() and notify() to pause a thread. I read talk about synchronizing, but I'm unsure how to do it in my instance. I have a music player with a progress bar where I want to pause the thread in control of syncing the progress bar with the music. Here is the thread I want to pause:
#FXML private void clickedButton(ActionEvent event){
shuffle.setOnAction(e -> {
artistPane.setText(model.getCurrentSong());
if(firstTime){
//Multithreading with JavaFX. Essentially this other thread will check the slider to make sure its on track.
sliderThread = new Task<Void>() {
#Override
protected Void call() throws Exception {
boolean fxApplicationThread = Platform.isFxApplicationThread();
System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);
//this is an infinite loop because now I only need to make this thread once, pausing and starting it, as opposed to making many threads
for(;;){
Thread.sleep(100);
progressBar.setValue(controller.getPercentageDone());
}
}
};
new Thread(sliderThread).start();
firstTime = false;
}else if(!model.getIsPlaying()){
//I want to start the thread here
}
controller.shuffle(); //this will start the music on the next song
});
Here is the second half where I also want to pause and start the thread:
play.setOnAction(e -> {
controller.play(); //this will pause/start the music
if(!model.getIsPlaying()){
//where I want to pause the thread.
}else{
//I want to start the thread here
}
});
I will try to give you simple example and you try to apply it to your program...
public class TestClass extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private Thread playThread ;
TestClass() {
playThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("DO SOME THING HERE");
System.out.println("SONG WILL PLAY.....");
}
});
}
public void startMyPlayer() {
System.out.println("PLAYING NOW...");
playThread.start();
}
public void pauseMyPlayer() throws InterruptedException {
System.out.println("PAUSED NOW...");
playThread.wait();
}
public void resumeMyPlayer() {
System.out.println("RESUMING NOW...");
playThread.notify();
}
}
That's it.I hope this help you.

How to keep progress indicator running in javafx

I want a progress indicator to stop only after completely updating the ui. But it stops after executing last line of code in ui method. The indicator should work as:
1> Start the progress
2> Run the progress until all nodes are added to the scene
3> Stop after completion
The way i update is, i pass BorderPane to the thread and set its center a gridpane, which is the last line of code after which the indicator stops.
And the loginTask, if i start it inside Application Thread the indicator does not spin !
borderpane.setCenter(gpane);
UI method
{
Loading loadBar = new Loading(stage);
Task<Boolean> loginTask= checkCredTask();
loginTask.setOnSucceeded(value -> {
loadBar.hideProgress(); });
loadBar.startTask(loginTask);
(new Thread(loginTask)).start();
}
Progress Bar
public class Loading{
private static Stage stage;
private static ProgressIndicator p;
private static Alert alert;
public Loading(Stage s){
stage=s;
p=new ProgressIndicator();
alert = new Alert(AlertType.NONE);
}
public void startTask(Task<Boolean> cm){
if(p != null){
p.setProgress(-1);
p.progressProperty().unbind();
p.progressProperty().bind(cm.progressProperty());
alert.initOwner(stage);
alert.getDialogPane().setStyle("-fx-background-color:rgba(0,0,0,0);");
alert.getDialogPane().getScene().setFill(Color.TRANSPARENT);
alert.initStyle(StageStyle.TRANSPARENT);
alert.getDialogPane().setContent(p);
alert.show();
}
}
public void hideProgress(){
alert.setResult(ButtonType.CLOSE);
}
}
Task
private Task<Boolean> checkCredTask() {
Task<Boolean> loginTask = new Task<Boolean>() {
#Override
public Boolean call() {
Boolean result = false;
int flag = verifyCredential();
if (flag == 1) {
loadUI();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = true;
} else if (flag == 2) {
result = false;
}
return result;
}
};
return loginTask;
}
load UI method
ExecutorService execsrv = Executors.newSingleThreadExecutor();
execsrv.execute(new AdminUI(stage,pane,mb));
execsrv.shutdown();
Your code won't even compile. Task<Boolean> loginTask does not override abstract call() method. Even if you wrap
ExecutorService execsrv = Executors.newSingleThreadExecutor();
execsrv.execute(new AdminUI(stage,pane,mb));
execsrv.shutdown();
in call() method it makes no sense, because you are executing new task inside another task.
Assumig that new AdminUI(stage,pane,mb) is long running process and return boolean you should do it in this way:
Task<Boolean> loginTask = new Task<Boolean>() {
#Override
protected Boolean call() throws Exception {
// Start the UI
AdminUI ui = new AdminUI(stage, pane, mb);
return ui.getBooleanValue();
}
};
EDIT
As I said, you are executing AdminUI task inside loginTask what makes no sense. For now you are waiting only for login task but not for AdminUI task. Login task finishes faster than AdminUI that is why indicator stops to early. Extract AdminUI to another Task. This is pseudo code so you have to do it by your self.
Task<Boolean> loginTask= checkCredTask();
loginTask.setOnSucceeded(value -> {
//****** THIS IS PSEUDO CODE ***********
//start AdminUITask
//AdminUITask.setOnSucceeded(value -> {
//loadBar.hideProgress();
//});
});

Infinite-while or for loop after ActionEvent not working in swing. why?

public void myMethod()
{
if (capture.isOpened()) {
while (true) { //This is The main issue.
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
my_panel.setimage(temp);
my_panel.repaint();
System.out.print("."); // It should prints "." but the above code doesn't works.
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}
This is invoking code of the above method...
actually it's an ActionEvent which can be fire on menu is clicked.
if (e.getActionCommand().equals("goLive")) {
System.out.println("Live...");
myMethod();
}
I know actually it's problem of the infinite while loop but here I need to put this condition at any cost.
The exact solution for this type of problem is Timer class. We can overcome this issue using the following code.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
myMethod();
}
}, 0);
Thanks google, oracle and java doc
Assuming that myMethod is called by an event listener (actionPerformed), the infinite loop is blocking the event dispatch thread.
You can avoid this by using SwingWorker or executing your loop on another thread:
public void myMethod()
{
if (capture.isOpened()) {
new Thread(new Runnable() { //Create a new thread and pass a Runnable with your while loop to it
#Override public void run() {
while (true) {
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
SwingUtilities.invokeLater(new Runnable() { //The following lines affect the GUI and must be executed on the event dispatch thread, so they should be wrapped inside a Runnable
#Override public void run() {
my_panel.setimage(temp);
my_panel.repaint();
}
}
try{
Thread.sleep(xxx); //consider waiting for a moment (e.g. 16ms)
} catch(InterruptedException e) { ... }
System.out.print(".");
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}).start(); //Let the thread loop in the background
}
}

Managing thread from a mouseclick

May be it is a basic question. But I'm a little confused about it. In my design I've a thread that is started from a mouse click. Method looks something like this:
Runnable r = new Runnable(){
public void run(){
A.firstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
}
};
new Thread(r).start();
Here B.FirstMethod(), B.SecondMethod(), B.ThirdMethod(); are accessing same variables and do some database operations during execution (i.e. locking, reading, writing etc.). But, If mouse is clicked during the execution or before finishing all the tasks I often get error message from database. How can I handle such type of situations. Here I cannot force the user to wait just with a simple Progressbar.
To handle such situation, you can disable the button once the thread has started its execution, and enable it again once the thread is going to finish its execution.
The code will then look like following:
Runnable r = new Runnable()
{
public void run()
{
button.setEnabled(false);
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
button.setEnabled(true);
}
};
new Thread(r).start();
Or when the button is clicked, you can use a boolean variable to check if the thread is in progress or not, and then decide as to what needs to be done like:
volatile boolean inProgress = false; // Instance Variable
Runnable r = new Runnable()
{
public void run()
{
inProgress = true;
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
inProgress = false;
}
};
if(!inProgress)
new Thread(r).start();
else
Popup some message perhaps

How to run a thread repeatedly after some interval

I want to run a thread (Which does some time consuming task in background and does NOT update UI) it just downloads some files form the internet and it is independent from the UI.
I want to run this thread repeatedly after some time interval.
How can i do this, I have thread something like below:
boolean mResult =false;
void onCreate()
{
DownloadThread mDownloadThread = new DownloadThread();
mDownloadThread.start();
}
class DownloadThread extends Thread implements Runnable
{
public void run()
{
// My download code
mResult = result;
}
}
Do i need to use Handler for implementing this?
Option 1:
volatile boolean flag = true;
public void run()
{
while(flag)
{
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
}
}
Option 2:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
}
}, 0, interval);
Option 3:
volatile boolean flag = true;
public void someMethod(){
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
if(flag)
return;
else
someMethod();
}
Option 4:
final Handler handler = new Handler();
volatile boolean flag = true;
Class A implements Runnable{
public void run(){
// Do your Task
}
if(!flag)
handler.postDelayed(a, interval);
}
A a = new A();
handler.postDelayed(a);
There will be many more options. I never tried option 3 and 4. It just came to my mind and I wrote. If I were you I would use any of 1 or 2.
Prefered choice is
java.util.concurrent.ScheduledExecutorService
Newer and robust implementation, More here ScheduledExecutorService
I would use a Timer to achieve this. Try this:
void onCreate()
{
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Download your stuff
}
}, 0, 1000);
}
It starts immediately and the run-Method gets called every second.

Categories

Resources