Im trying to make a window pop up when a certain condition is met, but when the condition is met. The window is not opening.I am using Thread.sleep
code:
public void grow() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(this.harvestTime);
if(water >= waterNeeded && fertelizer >= fertelizerNeeded) {
this.harvest = true;
AlertBox.display("CROP ALERT","A SEED HAS FINISHED GROWING");
Thread.sleep(60000);
if(harvest == true) {
withered = true;
harvest = false;
AlertBox.display("ALERT", "FAILED TO HARVEST A CROP. IT BECAME WITHERED!");
}
}
else {
this.withered = true;
}
} catch (Exception e) {
}
});
thread.start();
}
Java FX methods work only from Java FX thread. You cannot and should not use Java FX components / methods from background threads.
In case you need to show a notification from a background thread use:
Platform.runLater(new Runnable() {
#Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
In this case Runnable will be added to Java FX event queue and will be processed in Java FX thread.
Related
My Java code creates a thread on button click.
Every time if the button is clicked a thread is created.
I want to kill the previous thread if button is clicked again.
how can I do this?
below is the portion of code inside buttonclicklistener
myThread= new Thread()
{
public void run() {
diff2 = Math.abs(d3.getTime() - d1.getTime());
long diffseconds = diff2 /1000;
final long start = System.currentTimeMillis()/1000;
tv_timecount=(TextView)findViewById(R.id.tv_timeCount);
while(diffseconds>0)
{
tv_timecount.setText(String.valueOf(diffseconds--));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(myThread.isInterrupted())
break;
}
}
};
myThread.start();
I want to stop this Thread.
Many ways,
1: Using deprecated stop
Thread t = new Thread();
t.start();
t.stop(); //this is deprecated but it stops the thread
2: Using interrupt
Thread t = new Thread();
t.start();
t.interrupt();
3: Killing a thread with a while loop
boolean running = true;
Thread t = new Thread(() -> {
while (running) {
System.out.println("Running");
try { Thread.sleep(100); } catch (Throwable t) {}
}
});
t.start();
running = false;
You didn't mention why exactly you can't stop the thread, so I've some assumes which problems you might have.
1.Main reason why interrupt doesn't work in your code is because you catch InterruptedException and do noghing about that. But you should set interrupted flag by yourself after that, using Thread.currentThread().interrupt()
2.You can click the button 2 or more times at the same time, so all the clicks will try to stop the same thread, but every of them then start their own thread, so all but one of these thread (or pointer to them) will leak from you. This can be solved using synchronized function.
The general code, which handles button click should be looking like the code below:
private Thread myThread;
private synchronized void buttonClick() throws InterruptedException //NOTE synchronized
{
if (myThread != null) {
myThread.interrupt();
myThread.join();
}
myThread = new Thread(() -> {
diff2 = Math.abs(d3.getTime() - d1.getTime());
long diffseconds = diff2 / 1000;
final long start = System.currentTimeMillis() / 1000;
tv_timecount = (TextView) findViewById(R.id.tv_timeCount);
while (diffseconds > 0) {
tv_timecount.setText(String.valueOf(diffseconds--));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // NOTE: flag interrupt gets set
}
if (myThread.isInterrupted())
break;
}
});
}
Best way would be to use a flag. Introduce a flag inside your while method Add logic to check if flag is set and only then execute the code in your while loop.
while(diffseconds>0)
{
synchronized(Object.class){
if(flag == set) break;
}
//your code
}
You can reset/set flag on button click from other threads or the main execution.
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
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();
//});
});
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
}
}
How exactly do i call the .interrupt() method? When I have Thread.sleep(1000), when and where do I call the .interrupt() method? is it after? What I want to do is stop Thread.sleep(1000) midway.
EDIT::
i'm having trouble stopping a thread in the middle. This is part of my code, in the StoplightThread class I have problems on the first if statement. What it is supposed to do is wait at least 10 secs then allow the user to press the button so they can change the light, if the button is pressed it should stop the running thread in this case Thread.sleep(40000). What happens is when I press the button it changes the light but does not stop the thread. If I press the button while there is still 20secs left it will add 20secs to the 10secs for the yellow light, making it yellow for 30 secs.
Edit: if you are wondering, stoplightCanvas.x == 3 is green, stoplightCanvas.x == 2 is yellow, and stoplightCanvas.x == 1 is red.
class StoplightCanvas extends Canvas implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == cross) {
isPressed = true;
if (x == 3 && canCross)
x = 2;
}
repaint();
}
}
class StoplightThread extends Thread
{
StoplightCanvas stoplightCanvas;
StoplightThread(StoplightCanvas stoplightCanvas) {
this.stoplightCanvas = stoplightCanvas;
}
public void run()
{
if (stoplightCanvas.x == 3){
Thread.sleep(10000);
stoplightCanvas.canCross = true;
Thread.sleep(40000);
if(stoplightCanvas.isPressed)
StoplightThread.interrupt();
} else if (stoplightCanvas.x == 2) {
Thread.sleep(10000);
} else if (stoplightCanvas.x == 1) {
Thread.sleep(60000);
}
} catch (InterruptedException e){}
stoplightCanvas.toggleColor();
stoplightCanvas.repaint();
}
}
}
If you were going to call interrupt() at all, you'd call it from a different thread than the sleep().
If you want to interrupt the sleep() midway from the same thread, you can do this:
Thread.sleep( 500 );
...
Thread.sleep( 500 );
All that said, sleep() can be a code smell.
EDIT (after OP edit):
Call interrupt() on the StoplightThread from the GUI thread in your actionPerformed() method.
try this example
public class Test1 {
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
it prints
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at test.Test1$1.run(Test1.java:9)
You need a reference to the thread you want to interrupt, so that you can call interrupt() on it from a different thread.