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.
Related
(V1) I have a countdown object that deals with displaying a countdown on the JFrame by using a timer. Once the countdown goes to 0, I want the timer to stop and the game to start. However, I realized that even when my countdown isn't finished, my startGame() method is being run, and I cannot find a solution to make it so that the startGame() method only runs after the timer is stopped. So, my question is: is there anyway to make sure the startGame() only runs AFTER the countdown hits zero?
(V2) I tried using countdown.getTimer.isRunning()in the init() method to check whether or not the timer is running (if not then call startGame()) but that didn't seem to work. I'm guessing this is because at the time the if block is called, the timer is still running, so that's why startGame() isn't called... Is this why?
A little explanation of the code: the startCountdown() method tries to display the next image while hiding the last, so I have the catch for the first case where it tries to hide a non-existant image at an index that is out of bounds. Each time the timer ticks, I decrement sec by 1 until it is 0, and then the timer stops.
V1
public void init() {
countdown.startCountdown();
countdown.getTimer().start();
startGame();
}
public void startCountdown() {
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
if (sec == 0) {
countdownIcons.get(0).setVisible(false);
timer.stop();
}
countdownIcons.get(sec - 1).setVisible(true);
countdownIcons.get(sec).setVisible(false);
} catch (IndexOutOfBoundsException exception) {
if (sec == 0) {
timer.stop();
}
}
sec--;
System.out.println(sec);
}
});
}
V2
public void init() {
countdown.startCountdown();
countdown.getTimer().start();
if (!countdown.getTimer().isRunning()) {
startGame();
}
}
The problem is that the Timer method runs on a separate thread, different from your main thread.
The way I see it there are two possible solutions:
call your startGame() method inside startCountdown(), not inside init();
the second solution would be to pause your main thread and wait for startCountdown() to finish, something like this should work:
public void init() {
countdown.startCountdown();
countdown.getTimer().start();
// pause main thread until timer is notified
synchronized(timer){
timer.wait()
startGame();
}
}
public void startCountdown() {
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
if (sec == 0) {
countdownIcons.get(0).setVisible(false);
timer.stop();
// notify your current thread that it can resume execution
synchronized(timer){
timer.notify();
}
}
countdownIcons.get(sec - 1).setVisible(true);
countdownIcons.get(sec).setVisible(false);
// try not to catch this runtime exception and fix what causes IndexOutOfBoundsException
} catch (IndexOutOfBoundsException exception) {
if (sec == 0) {
timer.stop();
}
}
sec--;
System.out.println(sec);
}
});
}
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'm trying to learn Threads in Swing.
I have a Frame with a JProgressBar (progress), five JButtons (Start, Suspend, Resume, Cancel, Close), and a JLabel (label1).
The frame opens. Only Start is enabled. Start calls my class Progressor:
Updated Again Once and For All
Progressor progressor; //declared as class variable, initialized new in constructor and again in overridden done method
Here's the ButtonListener class:
public class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == jbStart) {
progressor.execute();
label1.setText("Progressing ...");
jbCancel.setEnabled(true);
jbResume.setEnabled(true);
jbSuspend.setEnabled(true);
jbClose.setEnabled(true);
}
if(e.getSource() == jbCancel) {
progressor.cancel(true);
label1.setText("Progress Canceled");
}
if (e.getSource() == jbSuspend) {
label1.setText(progressor.suspendProgress());
}
if (e.getSource() == jbResume) {
label1.setText(progressor.resumeProgress());
}
if (e.getSource() == jbClose) {
dispose();
}
}
}//buttonlistener
Here's the SwingWorker class:
public class Progressor extends SwingWorker<Void, Integer> {
private volatile boolean suspend = false;
private Object lock = new Object();
#Override
protected Void doInBackground() {
for (int i = 0; i <= 10; i++) {
checkForSuspend();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
publish(i);
}
return null;
}
#Override
protected void process(List<Integer> list) {
int value = list.get(list.size() - 1);
progress.setValue(value);
}
public void checkForSuspend() {
synchronized (lock) {
while (suspend) {
try {
lock.wait();
} catch (InterruptedException ie){
}
}
}
}//checkForSuspend
#Override
protected void done() {
label1.setText("All Done. Press close to exit");
progressor = new Progressor();
}
public synchronized String suspendProgress() {
suspend = true;
return "Progress suspended ...";
}
public synchronized String resumeProgress() {
synchronized (lock) {
suspend = false;
lock.notify();
return "Progress resumed ...";
}
}
}//Progressor class
Everything works except the cancel doesn't doesn't actually cancel the thread (the progress bar continues).
Should I suspend it before canceling?
This How to Pause and Resume a Thread in Java from another Thread question looks very similar to yours and has some nice examples in the answers.
As for your own code and why it does not work:
You create a new progressor on every click. You should be using and controlling one, instead of creating new ones every time.
When suspending your progressor finishes work instead of suspending. As the above question states - you should be looking at the flag at some points of your computation and acting on it. Example:
while (!cancel) {
if (!suspended) {
for (int i = 1; i <= 10; i++) {
Thread.sleep(1000);
publish(i);
}
}
}
The above code will suspend when it next reaches 10 (unless you resumed it before that), and finish when you press cancel (Cancel needs to be added as an extra flag in the obvious manner).
Your thread should run inside a while loop that looks for a boolean to change value from another object, then simply change the state with setPause(true/false) when you click the button:
while(true){
if(object_everyone_can_reference.getPause()){
Thread.sleep(1000);
}
}
I am having problem with multithreading.
When I am tring to use wait() and notify() or join() I am getting InterruptedException.
I have 2 threads in a WHILE loop and I want to wait until both of them are finished.
this is my code:
while (!GamePanel.turn)
{
if(GamePanel.s.isRunning)
{
synchronized (GamePanel.s.thread)
{
try {
GamePanel.s.thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//Player selected random moves
if(GamePanel.selectedMove == 1)
{
//Get computer's Random move.
strategy.getRandomMove();
}
else
{
//Player selected AI moves
if(GamePanel.selectedMove == 2)
{
//Get computer's AI move.
strategy.getMove();
System.out.println(strategy.move);
}
}
//Perform the next move of the computer.
Rules.makeMove(GamePanel.dimples, strategy.move, false);
}
both strategy.getMove() and Rules.makeMove() are threads.
for each thread I've created my own start() and stop() methods :
public void start()
//This function starts the thread.
{
if (!isRunning)
{
isRunning = true;
thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
private void stop()
//This function stops the thread.
{
isRunning = false;
if (thread != null)
{
thread.interrupt();
}
thread = null;
}
I have also tried to do thread.stop() but still same problem.
My question is how can I make the WHILE loop to wait until both threads are done??
You might consider to switching your code to use a CountDownLatch. You would create the latch like the following and all 3 threads would share it:
final CountDownLatch latch = new CountDownLatch(2);
Then your two threads would decrement the counter as they finish:
countDown.countDown();
And your waiting thread would do:
countDown.await();
It would be awoken after both of the threads finish and the latch goes to 0.
I am writing a simple game in Java, and I have a following issue:
I have a controlling class, called MainGameFrame, in which there is initialized gameThread. MainGameFrame has a key listener for Esc key, so that it pauses/resumes gameThread. However, this doesn't work:
public void keyPressed(KeyEvent e) {
// pause the game
synchronized(gameThread) {
if(e.getKeyCode() == e.VK_ESCAPE) {
try {
if(gameThread.getState() == Thread.State.WAITING) {
System.out.println("continue");
gameThread.notify();
System.out.println("after continue");
} else {
System.out.println("pause");
gameThread.wait();
System.out.println("after pause");
}
} catch (InterruptedException ex) {
Logger.getLogger(MainGameFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
It will pause on Esc and output "pause", but not "after pause".
gameThread.wait() doesn't make the gameThread thread to pause. It makes the current thread (i.e. the event dispatch thread) to wait. Since the EDT is waiting, it can't receive a keypressed event anymore: the entire GUI freezes
Read the Java tutorial on concurrency, and particularly the following page: http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
You should probably change the value of an AtomicBoolean variable, which is regularly inspected by the game thread to know if it has to pause. The game thread would then wait on a shared lock object. When resuming, change the boolean variable again and notify the game thread.
It waits until another thread calls notify(). Your not doing that, so "after pause" is never printed.
What do you want to achieve with gameThread.wait()?
You have the idea of wait and notify backwards.
One thread can not directly pause, or kill another thread. You can, however, change a variable that is shared between threads. When the interested thread sees that the variable has changed it may "pause" itself.
private static volatile boolean paused = false;
private static ReentrantLock pauseLock = new ReentrantLock();
private static Condition unpaused = pauseLock.newCondition();
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
if (!paused)
paused = true;
else {
pauseLock.lock();
try {
paused = false;
unpaused.signal();
} finally {
pauseLock.unlock();
}
}
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200,200));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
Thread gameThread = new Thread() {
public void run() {
while (true) {
System.out.println("running");
// presumably the game rendering loop
if (paused) {
pauseLock.lock();
try {
try {
unpaused.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
pauseLock.unlock();
}
}
}
}
};
gameThread.start();
}
I would also avoid using wait and notify directly as there are some caveats you must be aware of when using wait & notify (such as your thread that is waiting actually has to wait inside a loop because it can be woken up without notify ever being called).
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4308396
You should also be sure to always acquire and release locks in the following pattern, if not using synchronized blocks:
l.lock();
try {
// code
} finally {
l.unlock();
}
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
I'd also recommend reading:
http://www.javaconcurrencyinpractice.com/
There are more pitfalls than you would think when doing concurrent programming in Java.
The reason that one can not pause or kill a thread from another thread is that the thread doing the pausing or killing has no idea where in execution the other thread is and what resources the other thread might hold.
What would happen if Thread A paused Thread B and Thread B happened to hold several resources that Thread A will need later? What happens if Thread A kills Thread B while Thread B is using a resource that it is supposed to do some special clean up on?