Hi I'm using the next code to try to stop a thread, but when I see that Running is false it becomes true again.
public class usoos {
public static void main(String[] args) throws Exception {
start();
Thread.sleep(10000);
end();
}
public static SimpleThreads start(){
SimpleThreads id = new SimpleThreads();
id.start();
System.out.println("started.");
return id;
}
public static void end(){
System.out.println("finished.");
start().shutdown();
}
}
And the thread
public class SimpleThreads extends Thread {
volatile boolean running = true;
public SimpleThreads () {
}
public void run() {
while (running){
System.out.println("Running = " + running);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
System.out.println("Shutting down thread" + "======Running = " + running);
}
public void shutdown(){
running = false;
System.out.println("End" );
}
}
The problem is that when I try to stop it(I set running to false), it starts again..
Look at this line in the end method:
start().shutdown();
You are not stopping the original instance; you are starting another one, which you then immediately shut down.
There is no connection between your start and end methods—no information, no reference is passed from one to the other. It is obviously impossible to stop the thread you started in the start method.
Your end method should not be static; in fact, you don't even need it, shutdown is already it:
SimpleThreads t = start();
Thread.sleep(10000);
t.shutdown();
Because in the end method you just create a new Thread and kill it, save the thread instance and kill it:
Your code should look something like this:
public class usoos {
public static void main(String[] args) throws Exception {
SimpleThreads id = start();
Thread.sleep(10000);
end(id);
}
public static SimpleThreads start(){
SimpleThreads id = new SimpleThreads();
id.start();
System.out.println("started.");
return id;
}
public static void end(SimpleThreads id){
System.out.println("finished.");
id.shutdown();
}
Related
I'm learning concurrency knowledge in Java. About volatile keyword, it should make variable visible in different threads. But in my demo code, it doesn't seem to work as expected. The method run() in the class which implements Runnable will never stop.
public class VisibilityDemo {
public static void main(String[] args) throws InterruptedException {
TimeConsumingTask timeConsumingTask = new TimeConsumingTask();
Thread thread = new Thread(new TimeConsumingTask());
thread.start();
Thread.sleep(3000);
timeConsumingTask.cancel();
}
}
class TimeConsumingTask implements Runnable {
private volatile boolean toCancel = false;
#Override
public void run() {
while (! toCancel) {
System.out.println("executing...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (toCancel) {
System.out.println("Task was canceled.");
} else {
System.out.println("Task done.");
}
}
public void cancel() {
toCancel = true;
System.out.println(this + " canceled.");
}
}
In your main method you have two instances of your task:
public static void main(String[] args) throws InterruptedException {
TimeConsumingTask timeConsumingTask = new TimeConsumingTask(); //<-- one
Thread thread = new Thread(new TimeConsumingTask()); //<-- two
thread.start();
Thread.sleep(3000);
timeConsumingTask.cancel(); //<-- cancel() on first
}
}
You're passing one to the Thread constructor and then call cancel on the other one. You need to call cancel on the instance passed to Thread, like so:
public static void main(String[] args) throws InterruptedException {
TimeConsumingTask timeConsumingTask = new TimeConsumingTask();
Thread thread = new Thread(timeConsumingTask); //<-- difference here
thread.start();
Thread.sleep(3000);
timeConsumingTask.cancel();
}
}
I have been wanting for a long time to add schedulers to my API. So I set a class for the purpose. Here it is.
public abstract class SyncScheduler extends Scheduler {
private Thread thread = null;
private boolean repeating = false;
#Override
public synchronized void runTask() {
thread = new Thread(this);
thread.start();
}
#Override
public synchronized void runTaskLater(long delay) {
thread = new Thread(this);
try {
Thread.sleep(delay * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.run();
}
#Override
public synchronized void runRepeatingTask(long period) {
thread = new Thread(this);
repeating = true;
while (!thread.isInterrupted()) {
thread.run();
try {
Thread.sleep(period * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public synchronized void cancel() {
if (thread != null || !repeating) {
throw new SchedulerException("Scheduler is not started or is not a repeating task!");
} else {
thread.interrupt();
repeating = false;
}
}}
Scheduler just implements Runnable.
The problem is that whenever I try to create 2 or more Schedulers, the second one never starts until the first one is finished! For example if I have on Scheduler that runs every X seconds and I have another one the cancels it, the one that cancels the first one never starts! This is the problem.
How could I run two of these schedulers in parallel?
Also these are my two test main classes.
public class Test {
static Scheduler scheduler = new SyncScheduler() {
#Override
public void run() {
System.out.println("It works.");
}
};
public static void main(String[] args) {
scheduler.runRepeatingTask(1);
new SyncScheduler() {
#Override
public void run() {
System.out.println("Stopped.");
scheduler.cancel();
}
}.runTaskLater(2);
}}
And here's the second one.
public class Test {
static Scheduler scheduler = new SyncScheduler() {
#Override
public void run() {
System.out.println("It works.");
new SyncScheduler() {
#Override
public void run() {
System.out.println("Stopped.");
scheduler.cancel();
}
}.runTaskLater(2);
}
};
public static void main(String[] args) {
scheduler.runRepeatingTask(1);
}}
The first one outputs "It works." repeatedly until I force stop the test.
The second one gives me "It works." for once, then It gives me "Stopped." and with it and exception.
You are using the thread object wrongly.
To start a Runnable object (in this case, Thread object) in a different thread, the object must call start() method. You are using run() method, which just calling the method in the same thread without creating a new thread.
Try to change run() in SyncScheduler.runRepeatingTask and SyncScheduler.runTaskLater.
Also, I just noticed in your cancel() method:
if (thread != null || !repeating) {
throw new SchedulerException("Scheduler is not started or is not a repeating task!");
} else {
thread.interrupt();
repeating = false;
}
This would make the method throw exception if thread started. I think it should be if (thread == null || !repeating) {
I've a core method in my project which I need it to be synchronized in order not to be accessed twice at the same time, and hence I have a thread which uses an instance from this class to access this method, but inside this thread I need to have a long life loop to be used to access the same method with a fixed value so I have to use another thread in order to allow the first thread to move on and complete it's duties, but for sure the method doesn't run from that second thread using the same instance used in the first thread, and somehow I can't instantiate another instance from the class as I have to use this instance exactly, so how to overcome this problem.
below is the problem translated to java:
public class ClassOne {
synchronized public void my_method(int number) {
// Do some Work
}
}
public class ClassTwo {
private void some_method() {
Thread one = new Thread(new Runnable() {
#Override
public void run() {
ClassOne class_one = new ClassOne();
// DO Work
class_one.my_method(0);
run_loop(class_one);
// Complete Work
}
});
one.start();
}
boolean running = true;
private void run_loop(final ClassOne class_one) {
Thread two = new Thread(new Runnable() {
#Override
public void run() {
while (running) {
class_one.my_method(1); // won't run
Thread.sleep(10000);
}
}
});
two.start();
}
}
Actual problem overview:
my_method --- > is to send UDP packets.
the method has to be synchronized otherwise I'll get the socket is already open exception when trying to use it more than once repeatedly.
at some point, I have to send a KeepAlive message repeatedly each 10 seconds, so, I have to launch a separate thread for that which is thread two in run_loop method.
Putting something that will compile and work. I don't see why you need this function to be synchronized. Check the output for this program...The second thread access this method only when the first thread is done accessing (unless you have missed adding some additional code).
class ClassOne {
int criticalData = 1;
synchronized public void my_method(int number) {
// Do some Work
criticalData *= 31;
System.out.println("Critical data:" + criticalData + "[" + Thread.currentThread().getName() + "]");
}
}
class ClassTwo {
boolean running = true;
public void some_method() {
Thread one = new Thread(new Runnable() {
public void run() {
ClassOne class_one = new ClassOne();
// DO Work
class_one.my_method(0);
run_loop(class_one);
// Complete Work
}
});
one.start();
}
public void run_loop(final ClassOne class_one) {
Thread two = new Thread(new Runnable() {
public void run() {
while (running) {
class_one.my_method(1); // won't run
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
two.start();
}
}
public class StackExchangeProblem {
public static void main(String[] args) {
ClassTwo two = new ClassTwo();
two.some_method();
}
}
Where and how to implement addShutdownHook in a class, which have no main method? Can this used to kill all the active sockets initialized by that class?
This Might work for you,
public class AddShutdownHookSample {
public void attachShutDownHook(){
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Inside Add Shutdown Hook");
}
});
System.out.println("Shut Down Hook Attached.");
}
}
And in main Method:
public static void main(String[] args) {
AddShutdownHookSample sample = new AddShutdownHookSample();
sample.attachShutDownHook();
System.out.println("Last instruction of Program....");
System.exit(0);
}
Describe whole thing that you are trying to do and show the very exact point where you are having trouble this would be easier for other to help you.
The following is an example, this may help you
public class RuntimeDemo {
// a class that extends thread that is to be called when program is exiting
static class Message extends Thread {
public void run() {
System.out.println("Bye.");
}
}
public static void main(String[] args) {
try {
// register Message as shutdown hook
Runtime.getRuntime().addShutdownHook(new Message());
// print the state of the program
System.out.println("Program is starting...");
// cause thread to sleep for 3 seconds
System.out.println("Waiting for 3 seconds...");
Thread.sleep(3000);
// print that the program is closing
System.out.println("Program is closing...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Done like this...
static {
Runtime.getRuntime().addShutdownHook ( new Thread() {
public void run() {
server.shutdown();
}
} );
}
I have a main class which spawns a thread, let's call them MainClass and MyThread.
public class MainClass extends javax.swing.JFrame {
int sharedVariable;
MyThread threadInstance;
public MainClass (){
sharedVariable = 2;
threadInstance = new MyThread(this);
threadInstance.run();
}
public int getSharedVariable(){ return sharedVariable; }
public static void main(String[] args){
//begin main class
}
}
public class MyThread implements Runnable {
MainClass class;
public MyThread(MainClass main_class){
this.main_class= main_class;
}
#Override
public run(){
while(this.main_class is still active){
//grab status of sharedVariable and wait for x amount of time.
}
}
}
The problem is I do not know how to implement the while condition which checks if the MainClass instance is still alive and if it is, it has to use the this.main_class.getSharedVariable() to get the value of sharedVariable, then wait for x amount of time. MainClass has the main method .
I would recommend holding onto the Thread instance and then calling threadInstance.interrupt() right before the main(...) method exits.
Something like:
public static void main(String[] args){
MainClass mainClass = new MainClass();
try {
...
// do main stuff here
...
} finally {
mainClass.threadInstance.interrupt();
}
}
Then in your thread you'd do:
while(!Thread.currentThread().isInterrupted()){
...
}
You'd also want to handle InterruptedException correctly:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// always a good pattern to re-interrupt the thread here
Thread.currentThread().interrupt();
// if we are interrupted quit
return;
}
Btw, it is very bad form to leak the instance of an object during construction to another thread:
new MyThread(this);
See here: Why shouldn't I use Thread.start() in the constructor of my class?
Also, you aren't starting a thread when you call threadInstance.run();. You are just running it in the current thread. You should use threadInstance.start() but not inside of the constructor like that.
You can use CountDownLatch which is very convenient for such tasks as waiting other threads to finish some activity (you can change Thread.sleep(...) argument in main to, say, 12000L and see what happens):
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
class OtherThread extends Thread {
private final CountDownLatch sharedLatch;
OtherThread(CountDownLatch sharedLatch) {
this.sharedLatch = sharedLatch;
}
#Override
public void run() {
boolean wokenByMain = false;
try {
wokenByMain = sharedLatch.await(10000L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
return; // or not return, whatever makes more sense in your case
}
System.out.println("heh: " + wokenByMain);
}
}
class SOSample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
OtherThread otherThread = new OtherThread(latch);
otherThread.start();
System.out.println("Scheduled other thread to be started");
Thread.sleep(1000L);
System.out.println("going to release other thread");
latch.countDown();
}
}
public class MainClass extends JFrame implements Runnable {
public static void main(String [] args) {
final Thread t=new Thread(new MainClass() {
public void run(){
//something
});
Thread t2=new Thread(new MyThread() {
public void run() {
while(t.isAlive) {
//something
}
}
});
}
}