I am test a scenario to use volatile variable to stop one running thread from another.
I wonder why its not working. Where is the problem?
My code is:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
System.out.println("Working...");
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
public class Stopper extends Thread {
StoppableTask t ;
public Stopper(StoppableTask t){
this.t=t;
}
public void run(){
System.out.println("Ok..running too..");
try {
System.out.println("Waiting..");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.tellMeToStop();
System.out.println("Done Waiting..");
}
public class QuickTest{
public static void main(String[] args) {
StoppableTask t = new StoppableTask();
Stopper s = new Stopper(t);
t.start();
s.start();
}
}
I suspect that your program is printing so much output to the terminal that it is blocking waiting for the output to be displayed. It looks like it is not stopping but really it will. You just need to wait... for a long time...
You should put a Thread.sleep(100); inside of of the while() spin loop in StoppableTask.run() to slow down that output. Another way to do it is to remove the System.out and just increment a counter or something.
I just tried it and your program finishes in 5 seconds as expected:
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
// System.out.println("Working...");
}
System.out.println("Stopped task Done");
}
Your program is correct.
When working with threads i suggest you to use log4j instead of system.out.println.Configure the log4j to send output to a file.
You can search your string-pattern in a file. Its easy to analyse.
Related
I don't know how to make for a thread to run until the task is finished.
So i have this class:
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
System.out.println(3);
//here the next code to run
}
}
And another that try for example to add data in database:
public class ThreadRunnable implements Runnable{
public void run(){
//code to make the thread waits until the insert is done
//code for inserting data in database
}
}
So, inside method run() i want something like:
- try to insert data in database
- if connection to database is down, wait 5 seconds and try again
- if connection is ok, then insert data, and return successful message that data is added
Is this possible, and if yes, how?
Thanks!
You don’t need to wait for a thread. Just do the retries in a loop in your Runnable:
public void run() {
try {
while (true) {
try {
// Do database operations here
// Succeeded
break;
} catch (SQLException e) {
// Failed; log exception and try again.
logger.log(Level.INFO, "Couldn't save data.", e);
}
// Wait before trying again.
Thread.sleep(5000);
}
} catch (InterruptedException e) {
logger.log(Level.INFO, "Interrupted; exiting.", e);
}
}
Note: An interrupt is an explicit request for a thread to stop what it’s doing and self-terminate. The InterruptedException should not be caught inside the loop, because you want the loop to terminate in the event of an interrupt.
On the other hand, you do want the loop to keep executing in the event of an SQLException, so it should be caught inside the loop.
You can do something like that :
1) Add a waitFor function in your ThreadRunnable
2) Add synchronization via un LOCK variable
The code :
public class ThreadRunnable implements Runnable{
private boolean ended=false;
private final Object LOCK=new Object();
public void run(){
// do my stuff...
...
//at the end, notify the thread waiting for : it will wake up
synchronized(LOCK)
{
ended=true;
LOCK.notifyAll();
}
}
/**
Waits until the task is done
*/
public void waitFor()
{
synchronized(LOCK)
{
while(!ended)
{
//sleeps until notifAll is called (see run())
wait();
}
}
}
}
(in this code, you have to add the try/catch for the InterruptedException)
In your main :
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
t1.waitFor();
System.out.println(3);
//here the next code to run
}
}
import java.lang.Thread;
import java.util.Scanner;
class Running extends Thread{
private boolean Run=true;
public void shutdown(){
Run=false;
}
public void run(){
while(Run){
for(int i=0;i<1000;i++){
System.out.println("Starting Counter:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Volatile {
public static void main(String[] args) {
Running run1=new Running();
run1.start();
System.out.println("Press any key to stop thread execution");
Scanner sc=new Scanner(System.in);
sc.nextLine();
run1.shutdown();
}
}
I am using a volatile key word to stop the thread execution. But couldn't get the solution
What should I be doing to stop the thread execution?
So your post mentions the volatile keyword but I don't see it in the code you've posted. You need to make sure that Run is a volatile boolean so that it can be changed in the main thread and the other thread will see the changes.
private volatile boolean Run=true;
But I think the problem is that you are testing for this Run only in the outer while loop. Maybe you want it also in the inner counting loop. Something like:
for(int i = 0; i < 1000 && Run; i++) {
Right now, once the loop start counting it will have to finish before the Run boolean is checked. That may be 1000 seconds in the future.
You are using the right pattern, but apply it a bit wrong:
Your Runflag will only be checked after 1000 seconds, because it will only be checked after the for loop finished. Change your code to the following:
public void run(){
while(Run){
for(int i=0;(i<1000) && (Run == true);i++){
System.out.println("Starting Counter:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Please note you will have to completely remove the while loop if you don't want your for loop to be executed endlessly effectively.
A time ago the thread was stopped simply by calling the Thread's stop() function. Nowadays, it's deprecated because it's unsecure, so you have to stop the Thread from the inside of the Thread. You'll find a good example here. Keep in mind that doing this doesn't stop immediately the thread, it just tells it's available for stopping and Android will stop it whenever it finds it necessary.
Your code stays in the for-loop for 1000 seconds until it finally reaches the while(run) branch again. I guess this is why its not working properly.
These is the sample .You can create a boolean field and check it inside run:
public class Sample implements Runnable {
private volatile boolean isRunning = true;
public void run() {
while (isRunning) {
//do work
}
}
public void kill() {
isRunning = false;
}
}
To stop it just call
sample.kill();
This should work.
Take a look at this simple Java program:
import java.lang.*;
class A {
static boolean done;
public static void main(String args[]) {
done = false;
new Thread() {
public void run() {
try {
Thread.sleep(1000); // dummy work load
} catch (Exception e) {
done = true;
}
done = true;
}
}.start();
while (!done);
System.out.println("bye");
}
}
On one machine, it prints "bye" and exits right away, while on another machine, it doesn't print anything and sits there forever. Why?
This is because your boolean is not volatile, therefore Threads are allowed to cache copies of it and never update them. I would recommend an AtomicBoolean - that will prevent any issues you may have.
public static void main(String args[]) {
final AtomicBoolean done = new AtomicBoolean(false);
new Thread() {
public void run() {
done.set(true);
}
}.start();
while (!done.get());
System.out.println("bye");
}
By the time the main program's while loop is reached (which is also a Thread), the new Thread might be finishing its run() where done flag is set to true. Just to confirm this, you can add a sleep in the run() before done is set to true and then see if your bye is displayed on other machine also. Hope this would help.
When I run the program it does not display "HIIII."
I am a novice (sort of) so please dont "hate".
Is my wait() statement wrong? Or what am I doing wrong?
Is it the ArrayIndexOutOfBounds catch clause? Please help!
[edit] oh so is it the main method?? that it doesnt do anything?
[edit] i know the wait and notify is wrong... please don't mention it.
//this is the whole class
import javax.swing.*;
import javax.swing.JOptionPane;
public class none {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try{
if(tru = Boolean.parseBoolean(args[0])){
cheatMode = on;
System.out.println("Cheats are on.");
}
}
catch(java.lang.ArrayIndexOutOfBoundsException e){
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
}
public class console extends Thread{
public void run(){
try{
wait();
JOptionPane.showMessageDialog(null,"HIIII");
}
catch(Exception e){
e.printStackTrace();
System.out.println("The console glitched...");
}
//hiiii
JOptionPane.showMessageDialog(null,"HIIII");
}
public class mainThingy extends Thread{
public void run() {
if(game = on)
notify();
}
}
}
}
There seems to be couple of issues
1) if(tru = Boolean.parseBoolean(args[0])){
Above statement is assignemt and not comparison. Use == operator.
2) Wait and notify should always be called from inside Synchronized blocks. Your code doesn't seem to be doing that.
I'd advise against the standard wait()-notify() structures. There are way better methods for this: the Java concurrency package.
Tutorial for Java Concurrency
API JavaDoc
JCIP, or Java Concurrency In Practice (Peierls, Bloch, Bowbeer, Holmes, Lea)
And as you seem to be in your first steps in learning Java, I'd suggest another two books:
Effective Java (Bloch)
Java puzzlers (Bloch, Gafter)
>java none true will print only Cheats are on. But your question is about printing Hiii. Isn't it ? You have got that in JOptionPane dialog inside the console class. Without initializing it how can you expect your program to print Hiii?. Also why have you written two public classes in one file ? When you are calling wait and nottify methods, you are also missing the synchronized statement. So when you start your threads console and mainThingy those will throw IllegalMonitorStateException anyways. So actually what are you trying to do ?
You main method doesn't actually start anything
wait and notify must be synchronized on the same monitor/lock
Your two threads are not sharing the same monitor/lock
if (game = on) in mainThingy is an assignment, not a check, it should be if (game == on)
UPDATE with Example
public class TestThread {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try {
if (args.length > 0) {
if (tru = Boolean.parseBoolean(args[0])) {
cheatMode = on;
System.out.println("Cheats are on.");
}
}
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
Console con = new Console();
con.start();
// Give time for the console thread to get started
do {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(TestThread.class.getName()).log(Level.SEVERE, null, ex);
}
} while (!con.isAlive());
System.out.println("Start main...");
Console.MainThingy main = new Console.MainThingy();
main.start();
}
public static class Console extends Thread {
// A shared lock that our two threads can communicate on...
public static final Object WAIT_LOCK = new Object();
public void run() {
try {
System.out.println("Waiting...");
// Must "own" the monitor before we can call wait
synchronized (WAIT_LOCK) {
WAIT_LOCK.wait();
}
JOptionPane.showMessageDialog(null, "HIIII");
} catch (Exception e) {
e.printStackTrace();
System.out.println("The console glitched...");
}
}
public static class MainThingy extends Thread {
public void run() {
if (game == on) {
// Must "own" the monitor before we can call notify
synchronized (WAIT_LOCK) {
System.out.println("Notify...");
WAIT_LOCK.notify();
}
}
}
}
}
}
Java Concurrency is fun, but it will bite you if you're not careful with it and treat it nicely.
Take a read through Currency in Java
I have a JRuby engine which evaluates some scripts and I want to close the thread if it takes more than 5 seconds.
I tried something like this:
class myThread extends Thread{
boolean allDone = false;
public void threadDone() {
allDone = true;
}
public void run() {
while(true) {
engine.eval(myScript);
if(allDone)
return;
}
}
(...)
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
if(th1.isAlive())
th1.threadDone();
} catch(InterruptedException e) {}
if(th1.isAlive())
System.out.println("Still alive");
I also tried to kill the thread with th1.stop() or th1.interrupt() but the value retured by th1.isAlive() method is always true.
What can I do?
I want to add that myScript could be "while(1) do; end" and I cannot wait until it's completed. So I want to prevent scripts like that and kill the thread if it takes more than 5 seconds.
Another solution would be to use the built-in mechanism to interrupt threads:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
engine.eval(myScript);
}
}
...
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
th1.interrupt();
}
This way, no need for an allDone field, and no risk in failing to synchronize.
To make your Thread stoppable you might want something like.
class MyTask implements Runnable {
public void run() {
try {
engine.eval(myScript);
} catch(ThreadDeath e) {
engine = null; // sudden death.
}
}
}
You can call Thread.stop(), but I suggest you read the warnings on this method first.
If you want a thread to run for up to 5 seconds, the simplest solution is for the thread to stop itself.
class MyTask implements Runnable {
public void run() {
long start = System.currentTimeMillis();
do {
engine.eval(myScript);
} while(System.currentTimeMillis() < start + 5000);
}
}
This assumes you want to run engine.eval() repeatedly. If this is not the case you may have to stop() the thread. It is deprecated for a good reason but it might be your only option.