I want to make an easy app. But I want to stop thread with a button. This code doesn't work. I saw all web sites like this way. I don't understand why not working.
Thread is starting with a btnStart.
btnStop isn't working. I wrote stopThread() function for stopping.
Which how this can do another way? Any idea?
private volatile boolean isRunning;
==============
private void stopThread() {
isRunning=false;
Thread.currentThread().interrupt();
}
==============
private final void runThread() {
new Thread() {
public void run() {
while (isRunning) {
try {
Random r = new Random();
islemler[0] = "+";
islemler[1] = "-";
islemler[2] = "*";
islemler[3] = "/";
for (int i = 0; i <10; i++) {
islem1 = islemler[r.nextInt(4)];
islem2 = islemler[r.nextInt(4)];
islem3 = islemler[r.nextInt(4)];
islem4 = islemler[r.nextInt(4)];
txt1.setText("1"+islem1+"1");
txt2.setText("1"+islem2+"1");
txt3.setText("1"+islem3+"1");
txt4.setText("1"+islem4+"1");
Thread.sleep(150);
Thread.sleep(50);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
==============
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
isRunning=true;
runThread();
**This part is working**
}
});
==============
btnStop = new JButton("Stop");
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopThread();
**But this part is not working. Can you help??**
}
});
The Problem
You have two threads open, possibly three if you have one set aside for the ui.
The first thread is the one the program launches on, and the second would be where you creating the random object and for-loop. When you are calling "stop thread" you are doing so from either the main thread or the third thread for the ui.
This means that
Thread.currentThread().interrupt();
is not closing the correct thread.
The Solution
For a solution to this problem, look at this GeeksForGeeks article which suggests storing threads as a variable and then you can reliably call the interrupt method on it.
Related
I have some doubts about the use of the methods wait() and notify(). I have the next code which has some button events, the first time the user pushes the button it has to stop printing, and the second time it restarts printing again. I understand that is better to use Runnable instead of Thread, but I have to use Thread because of the requirements. The code works fine the first time the button is pushed but the second time it doesn´t, I want to use the wait() and the notify, but i don´t know how to do it with this particular code.
class Thr extends Thread{
private int count = 0;
private long pause;
private boolean canPrint = true;
private JTextArea textArea;
Thr(long miliseconds,JTextArea text){
pause = miliseconds;
textArea = text;
}
public void pushedButton(){
if(canPrint)
this.canPrint = false;
else
this.canPrint = true;
}
public void run()
{
while(this.canPrint)
{
try
{
this.printCounter();
Thread.sleep(pause);
this.count++;
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
public void printCounter(){
String time;
time = Integer.toString(count);
textArea.setText(time);
}
}
class Interface extends JFrame implements ActionListener{
private JTextArea textArea,textArea2;
private JButton button;
private Thr thread,threadEvent;
Interface()
{
textArea = new JTextArea(10,7);
textArea2 = new JTextArea(10,7);
thread = new Thr(2000,textArea);
threadEvent = new Thr(1000,textArea2);
button = new JButton("Pausar/Reanudar");
this.getContentPane().add(button,BorderLayout.SOUTH);
this.getContentPane().add(textArea,BorderLayout.WEST);
this.getContentPane().add(textArea2,BorderLayout.EAST);
thread.start();
threadEvent.start();
button.addActionListener(this);
}
public void actionPerformed(ActionEvent event)
{
threadEvent.pushedButton();
}
}
public class MensajesHilos {
public static void main(String[] args){
Interface i = new Interface();
i.setTitle("Control Threads");
i.setBounds(200, 200, 300, 240);
i.setVisible(true);
}
}
The way you have coded, if you want to achieve the desired result,
I feel the modification need to be done in run method,
public void run()
{
while(true)
{
if(this.canPrint){
try
{
this.printCounter();
Thread.sleep(pause);
this.count++;
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
in this way, your Thread will never go dead and toggle printing based on canPrint boolean value.
Also, make sure to declare canPrint variable volatile, so that changes to it will be directly written to main memory and reflected immediately.
"button event doesn´t work properly"
This is false, if you put a print statement in the actionPerformed method, you will see that it is called every time you press the button.
By the way note that you can simplify this
if(canPrint)
this.canPrint = false;
else
this.canPrint = true;
To
this.canPrint = !this.canPrint;
Note that it is a good practice to always put #Override anotation on top of overriden method.
#Override
public void actionPerformed(ActionEvent event)
{
threadEvent.pushedButton();
}
Now why don't you get the expected result ?
You ommit to call thread.pushedButton, so the canPrint will only be reseted in the threadEvent object, and will never be in thread.
Note that once the boolean are set to false, you will exit the loop and the process won't start back after even if you re-set the boolean value to true. This example will works using while(true) however, you should change the true to any sentinel value to handle the exit of the program as this will loop forever.
#Override
public void run()
{
while(true)
{
if(this.canPrint)
{
this.printCounter();
this.count++;
}
try
{
Thread.sleep(pause);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Also, make sure that pause is never 0 else you will eat all of the computer process.
Note that, as other stated, you should declare variables that are accessed in thread as volatile (canPrint) in your case.
I am following a guide that shows how to create a Pong game. There is a part, where I am supposed to create a Thread, and call a function that moves the ball.
This is the code I created:
package com.ozadari.pingpong;
public class PingPongGame extends Thread {
private Ball gameBall;
private PingPongView gameView;
public PingPongGame(Ball theBall,PingPongView mainView)
{
this.gameBall = theBall;
this.gameView = mainView;
}
#Override
public void run()
{
while(true)
{
this.gameBall.moveBall();
this.gameView.postInvalidate();
try
{
PingPongGame.sleep(5);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}}
The thread is called and working, but it doesn't print anything. I tried to cancel the infinte loop and make the loop run 100 times. After I wait a while, it prints to the screen as it should be after 100 runs, but it doesn't print anything in the middle.
What is the problem? How can I fix it?
Unsure from the code you've posted but anyway, you can use a handler and have it run once every second like so (change the time to what you want):
Handler handler = new Handler();
final Runnable r = new Runnable()
{
public void run()
{
//do your stuff here
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
http://developer.android.com/reference/android/os/Handler.html
You can also use a normal thread, and call start at the end.
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
public class Signal2NoiseRatio
{
public ImagePlus SingleSNR(ImagePlus imagePlus) throws InterruptedException
{
new Thread()
{
#Override public void run()
{
JFrame imageFrame = new JFrame("ROI");
Container imageFrame_Container = imageFrame.getContentPane();
IIImagePanel imagePanel = new IIImagePanel();
imageFrame_Container.add(imagePanel);
imagePanel.setImage(imagePlus.getImage());
imagePanel.getDisplayedImage();
imageFrame.setVisible(true);
final SNRSingleImageListener sNRSingleListener = new SNRSingleImageListener(imagePanel);
imagePanel.addMouseListener(sNRSingleListener);
imagePanel.addMouseMotionListener(sNRSingleListener);
}
}.start();
new Thread()
{
#Override public void run()
{
for (int i = 0; i <= 2000; i++)
{
System.out.println("schleife "+i);
// ask if useractions are done ..
}
synchronized( Signal2NoiseRatio.this )
{
Signal2NoiseRatio.this.notifyAll();
}
}
}.start();
synchronized (this)
{
this.wait();
// if userinteractions are done, go on
}
return imagePlusToProcess;
}
}
The first new Thread() perform a frame which presents an image in it. My intention was to present the image in a new thread to wait for some user interactions on the image. But the code leads the frame to a white window and the image is not visible and the frame is not usable.
In the second thread I want ask in a short interval if the user actions are done.
It is not really a nice solution but it is be possible? what's wrong here?
Thank you stackoverflow!
I can see a few problems here:
1.If this
synchronized (this)
{
this.wait();
// if userinteractions are done, go on
}
is happening on the UI thread, then you will block it from receiving user input (or doing anything else) until the object is signaled.
2.This part seems pretty much overcomplicated:
new Thread() {
#Override
public void run() {
for (int i = 0; i <= 2000; i++) {
System.out.println("schleife " + i);
// ask if useractions are done ..
}
synchronized (Signal2NoiseRatio.this) {
Signal2NoiseRatio.this.notifyAll();
}
}
}.start();
synchronized (this) {
this.wait();
// if userinteractions are done, go on
}
Just use:
Thread t = new Thread() {
#Override
public void run() {
for (int i = 0; i <= 2000; i++) {
System.out.println("schleife " + i);
// ask if useractions are done ..
}
}
}.start();
t.join();
Unless you're signaling more than what you had above. But again, this is redundant, since starting a thread only to wait for it to finish does not make much sense...
Problem solved.
The invoker of the method was an AWT-Thread. I created a new Thread for the invoker and so the AWT-Thread was not blocked and the then frame and image could present correctly.
Thank you all for your help.
First code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class cos {
public static int a;
private static JLabel labeler;
// public static Runnable r1;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
a = 0;
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
cos window = new cos();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public cos() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
public void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 205, 194);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblTime = new JLabel("Time:");
frame.getContentPane().add(lblTime, BorderLayout.WEST);
final JLabel labeler = new JLabel("");
frame.getContentPane().add(labeler, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
Runnable r1 = new Runnable() {
public void run() {
while (a <= 10) {
a = a + 1;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
public void actionPerformed(ActionEvent arg0) {
Thread threder = new Thread(r1);
threder.start();
// liczniczek bla = new liczniczek();
}
});
frame.getContentPane().add(btnNewButton, BorderLayout.SOUTH);
}
public void licznik() {
while (a < 60) {
a = a + 1;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
And now my question. I wanna use code like this:
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
But that doesen't work. What i must do to separate this code ? Sorry for my bad english
Sierran.
never use Thread#sleep(int) during EDT, sure if is there only this thread then works correctly (with blockng EDT),
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
is wrong than same as you call plain licznik();, you have to wrap that this way
Runnable r1 = new Runnable(){
public void run(){
labeler.setText(Integer.toString(a));
}
};
but again without Thread#sleep(int), you have three choises
1) change Thread to the javax.swing.Timer
2) change Thread to the Runnable#Thread, there you can delaying with Thread#sleep(int), but output to the GUI must be
Runnable r1 = new Runnable(){
public void run(){
labeler.setText(Integer.toString(a));
}
};
3) use SwingWorker, where output is in the EDT and you can use Thread#sleep(int) too
example Thread#sleep(int) during EDT
put all together
EDIT
don't use reserved words as class, method, variable, whatever Name in the Programing languages (meaning cos)
your code works by implements all three options that I post here,
What do you mean "it doesn't work"? It works for me. How are you trying to use this code, and what errors or problems are you having when you run it? Myself, I'd use a SwingWorker though and I'd set the JLabel's text via the SwingWorker's publish/process method pair. To learn more on how to use this, please see this tutorial: Concurrency in Swing
Edit
Actually, an easier way to accomplish what you want is to not use threads or Runnables directly at all but to use a Swing Timer as they're built for just this case. For more on this, please check out the Swing Timer Tutorial
I gather that you want the function licznik() to run in a separate thread. You create a Runnable, but you have to do something more to make its run() method execute. There are a couple of ways to do this:
Runnable r1 = new Runnable(){
public void run(){
licznik();
}
};
new Thread(r1).start();
or you can just subclass Thread directly:
Thread r1 = new Thread(){
public void run(){
licznik();
}
};
r1.start();
Runnable interface has no method licznik(). You can create class that implements Runnable with licznik() method.
Or if you do not need to reuse this method and use it just once, then the fastest way is to move its implementation inside new Runnable() block
Runnable r1 = new Runnable(){
public void run(){
this.licznik();
}
public void licznik(){
while (a < 60){
a = a + 1 ;
labeler.setText(Integer.toString(a));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Look on GitHub under at https://github.com/greggwon/Ham. Look at the source code in https://github.com/greggwon/Ham/blob/master/SwingUtil/src/org/wonderly/swing/ComponentUpdateThread.java to see how I've packaged this whole detail into a single class which uses anonymous inner classes to do the work. It would be possible to change this to lambdas now, but I have not used Java in several years and thus haven't made that change.
new ComponentUpdateThread( new Action[] { add, del, edit } ) {
public void setup() {
super.setup();
list.setEnabled(false);
list.clearSelection();
}
public Object construct() {
try {
Vector v = remote.getData();
Collections.sort( v );
return v;
} catch( Exception ex ) {
reportException(ex);
}
return null;
}
public void finished() {
try {
Vector v = (Vector)getValue();
if( v != null ) list.setListData(v);
} finally {
super.finished();
list.setEnabled(true);
edit.setEnabled(false);
del.setEnaled(false);
}
}
}.start();
With this style of work, you can use final values from surrounding blocks or other class visible data to control various aspects of what happens before, during and after background thread execution.
I've change this code around over the years in various ways and there are other variations of this that exist.
The arguments to the ComponentUpdateThread constructor are controls/actions to be "disabled" while the background thread is running. Other enable/disable activities can be more literally embedded into the activities in setup() and finished() (which are run in the AWT event thread) before "construct" is run in the background thread.
I've come again in one of THOSE situations where it is just impossible to stop/destroy/suspend a thread. .interrupt() doesn't do the trick and .stop() and .suspend() are deprecated.
Very simple example:
public class TimerThread extends Thread {
private JPanel colorPanel;
public TimerThread(JPanel colorPanel) {
this.colorPanel = colorPanel;
}
public void run() {
while (true) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}
}
What this does is repaint a certain JPanel every second to change its colour. I want to start and stop the thread like this from another class:
timer = new Thread(new TimerThread(colorPanel));
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.interrupt();
}
});
Obviously (?) this doesn't work... I know I could use a Timer, a SwingWorker or declare the timer as timer = new TimerThread(colorPanel); and use a boolean instead of "true" in the run method, but I've been asked to declare timer as a "Thread" and nothing else.
To my surprise (or is this that stupid?), even this didn't work:
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer = new Thread(new TimerThread(colorPanel));
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.interrupt();
timer = null;
}
});
So my question is simple: How do you make threads Start/Pause/Resume/Stop in Java?
when you get an interrupt you should start the cleanup and return a.s.a.p. (or at the very least reset the interrupted status)
while (true) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch(InterruptedException e){//from sleep
return;//i.e. stop
} catch (Exception ex) {
//do Nothing
}
}
another way is to check Thread.interrupted() in the condition (but you'll need to reset the interrupted status in the catch of InterruptedException
however in swing you can use javax.swing.Timer to let an event run every so often and stop that with the api of that
javax.swing.Timer timer = new Timer(1000,new ActionListener() {
public void actionPerformed(ActionEvent e) {
colorPanel.repaint();
}
});
timer.setRepeats(true);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
Try this:
public class TimerThread extends Thread {
private volatile boolean stop = false;
private JPanel colorPanel;
public TimerThread(JPanel colorPanel) {
this.colorPanel = colorPanel;
}
public void stopTimer() {
stop = true;
}
public void run() {
while (stop == false) {
try {
Thread.sleep(1000);
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}
}
// Why new Thread(new TimerThread(...))?
// timer = new Thread(new TimerThread(colorPanel));
timer = new TimerThread(colorPanel)
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stopTimer();
}
});
Also have a look at here to see how you can replicate stop now that it's deprecated.
You make them co-operate, basically. You have some shared flags to let them see what they should be doing, and whenever you would sleep, instead you wait on some shared monitor. Then when you want to control the thread, you set the appropriate flag and notify the monitor so that if the thread was waiting, it will wake up and notice that it should suspend/stop/whatever. Obviously you need to take the normal sort of care around shared state, using volatile variables, Atomic* objects or locking to make sure that every thread sees the updates made by every other thread.
Anything non-cooperative is risky due to the chance of corrupting state half way through an operation.
It is dangerous to stop threads pre-emptively. Doing so leads to deadlocks, resource leaks and so on. Instead you should use a cooperative signaling mechanism.
Signal to the thread that you want it to stop, and then wait for it to do so. The thread should regularly check whether it needs to stop and react accordingly.
Instead of looping while (true), you should loop while the thread is not interrupted:
#Override public void void() {
// some kind of initialization...
while (!Thread.currentThread().isInterrupted()) {
try { ...
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // ensure interrupt flag is set
}
}
// some kind of cleanup
}
If InterruptedException is not thrown by anything inside your while block, either you don't use blocking operations (and simply calling Thread.interrupt() on this thread would stop it the next iteration) or you use some blocking calls that are not well behaved (there are many such examples in the JCL itself!).
The correct way to do this is indeed to have a variable that determines when the Thread should be stopped, exiting from its run method. You can find more information about how to do this properly here
With this solution you won't get "instantaneous" updates that you could get with wait/notify or interrupt, but if you don't mind the fraction of a second delay, it should do the job.
volatile boolean stopped = false;
volatile boolean paused = false;
pauseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
paused = true;
}
});
resumeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
paused = false;
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopped = true;
}
});
... TimerThread
public void run() {
while (stopped == false) {
try {
Thread.sleep(1000);
if (stopped)
break;
if (!paused)
colorPanel.repaint();
} catch (Exception ex) {
//do Nothing
}
}
}