public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
}
}
}).run();
System.out.println("Bye");
}
In the main thead, I create a new thread, which will print "hello" every second. Why the final "Bye" never got print? In the other word, why the child thread blocks the main thread?
Because you are calling run(), instead of start().
You must never call run() directly. If you call start(), the program will call run() for you, in a different thread. (Like you wanted.) By calling run() yourself, you are going into the run() method with the parent thread, and get stuck in an eternal loop, with your parent thread.
Related
I'm attempting to start another thread that branches from the main thread when thread.start() is called. But it appears to take the main thread in to the thread class. Here is minimum reproducible code of my issue. Thanks for looking.
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadWhileLoop threadWhileLoop = new ThreadWhileLoop();
//threadWhileLoop.run();
threadWhileLoop.start();
while (true){
Thread.sleep(1000);
System.out.println("Main Thread is doing its thing");
}
}
}
and here is the extended thread class
public class ThreadWhileLoop extends Thread {
#Override
public synchronized void start() {
super.start();
while (true){
System.out.println("ThreadWhileLoopIsRunning");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void run() {
super.run();
while (true){
System.out.println("ThreadWhileLoopIsRunning");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Expected output:
ThreadWhileLoopIsRunning
Main Thread is doing its thing
ThreadWhileLoopIsRunning
Main Thread is doing its thing
ThreadWhileLoopIsRunning
Main Thread is doing its thing
Actual output:
ThreadWhileLoopIsRunning
ThreadWhileLoopIsRunning
ThreadWhileLoopIsRunning
Don’t override start. The start method is used by the calling thread to get the new thread into a runnable state. There are very few good reasons to override it. In your posted code the whole program is running in the main thread.
What you need to do is override the run method in the new thread. Then have the main thread call start, which will cause the run method to execute in a separate thread.
(It would be better to create a Runnable than to override Thread. You can pass the Runnable into the Thread as a constructor argument. With this approach there is less temptation to tamper with the Thread object.)
You can check what thread is running with
System.out.println(Thread.currentThread().getName());
In another answer I have an example of starting a thread using a Runnable: https://stackoverflow.com/a/5915306/217324
I'd like to run a thread from the main thread , but I want this thread to be executed after the main thread is finished.
How should I do it ?
Can I pass the thread a reference to the main thread and call to join() method ?
The closest would be a shutdownHook,
Runtime.getRuntime().addShutdownHook(new Thread(){
...
});
But this would run will the process is still alive, once the process dies, thats it, you can't add any threads to a process that doesn't exist anymore.
You can use the Runtime.getRuntime() method for this. Here is an example:
public static void main(String[] args) {
.....
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){
public void run(){
// run when the main thread finishes.
}
}));
}
You can find more details about this in the documentation
You can artificially do this with basic thread objects as follows, although I would recommend using the other answers on shutdown hooks instead.
public static void main(String[] args) throws Exception {
// parametrizes with current thread
new Deferrable(Thread.currentThread());
System.out.println("main thread");
}
static class Deferrable extends Thread {
Thread t;
Deferrable(Thread t) {
this.t = t;
// optional
// setDaemon(true);
start();
}
#Override
public void run() {
try {
// awaits termination of given Thread before commencing
t.join();
System.out.println("other thread");
} catch (InterruptedException ie) {
// TODO handle
}
};
}
This will always print:
main thread
other thread
The typical synchronizer for this situation is a CountDownLatch. Have the spawned thread wait for the CountDownLatch prior to doing what it needs to, and have the main thread finish by calling CountDownLatch.countDown()
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(1); // will need only one countDown to reach 0
new Thread(() -> {
try {
latch.await(); // will wait until CountDownLatch reaches 0
// do whatever is needed
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// do stuff
// end main thread
latch.countDown(); // will make the latch reach 0, and the spawned thread will stop waiting
}
This question already has answers here:
How to start anonymous thread class
(9 answers)
Closed 9 years ago.
public Thread thread = new Thread();
public void start() {
running = true;
thread.start();
}
public void run() {
while(running) {
System.out.println("test");
try {
thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My problem is that the program will not print out "test" nor will it seem to loop despite 'running' being true. Is there a way I can continuously loop in the run method?
You haven't actually asked run() to be called. All you've done is declare a run() method unrelated to the Thread.
Put your run() method in a Runnable and pass that to the Thread.
public Thread thread = new Thread(new Runnable() {
public void run() {
while (running) {
System.out.println("test");
try {
thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
The problem appears to be that you aren't running the run method that you think you're running in the thread.
First, you've created a Thread called thread. In your class's start method, you set running to true and call thread.start(). But that just calls Thread's run() method, which does nothing.
public void run()
If this thread was constructed using a separate
Runnable run object, then that Runnable object's run method is called;
otherwise, this method does nothing and returns.
You aren't calling your own run method.
You have created a run method. I can't see your class definition here, but I'm assuming that your class implements Runnable. You need to send an instance of your class as an argument to the Thread, by using the Thread constructor that takes a Runnable. Then the Thread will know to run your Runnable's run() method.
Well you need to call start() to start the thread. Otherwise neither running will be true
nor thread.start() get executed. Well i can guess you were intended to do something like this:
class MyTask implements Runnable
{
boolean running = false;
public void start() {
running = true;
new Thread(this).start();
}
public void run() {
while(running) {
System.out.println("test");
try {
Thread.sleep(1000);
// you were doing thread.sleep()! sleep is a static function
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
new MyTask().start();
}
}
My Problem:
I want to run a method from a Thread, which is no Thread but might take some time to execute (e.g. waiting for server response). It is important that my none thread method is in another class (the classes are Objects which are used in other classes too).
If you do this as in the example code, the whole program will pause for 10 seconds, but I want it to continue with other program code.
Is there a good way of doing this?
My code:
MyThread.java (extends Thread)
public Foo foo;
public void run() {
foo.bar();
}
Foo.java
public void bar() {
try {
Thread.sleep(10000);
// Represents other code that takes some time to execute
// (e.g. waiting for server response)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
And a main method:
public static void main(String[] args) {
MyThread t = new MyThread();
t.foo = new Foo();
System.out.println("Starting!");
t.run();
System.out.println("Done!");
}
You don't want to call run() on the Thread, you want to call start().
Assuming MyThread extends Thread, you need to call start() not run().
Calling run() is just calling a method synchronously.
public static void main(String[] args) {
MyThread t = new MyThread();
t.foo = new Foo();
System.out.println("Starting!");
t.start(); // change here
System.out.println("Done!");
}
start() actually starts an OS thread to run your code on.
Use start() rather than run() on your thread. Or else it will be just like the main thread calling a method of another thread which means you are calling wait() on the main thread itself.
don't call run() method directly.
call start() method instead of run() method.
when call run() method directly
this thread go to main stack, and it run one by one.
class MyThread extends Thread{
public Foo foo;
public void run() {
foo.bar();
}
}
class Foo{
public void bar() {
try {
boolean responseCompleted = false;
boolean oneTimeExcution = false;
while(!responseCompleted){
if(!oneTimeExcution){
// Represents other code that takes some time to execute
oneTimeExcution = true;
}
if( your server response completed){
responseCompleted = true;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread t = new MyThread();
System.out.println("Starting!");
t.start();
System.out.println("Done!");
}
The following code blocks in synchronized sync() method before calling plain() method. Why is this so, shouldn’t the intrinsic lock block call to synchronized methods only – for example this behavior would have been fine if plain() was synchronized as well.
As the monitor concept that java uses is applicable to synchronized methods/blocks only – it by definition should not affect execution of non synchronized code. Is this always the case or is this behavior JVM implementation specific.
public class Main {
public static void main(final String[] args) {
final Main main = new Main();
new Thread(new Runnable() {
#Override
public void run() {
main.sync();
}
}).run();
main.plain();
}
public synchronized void sync() {
try {
System.out.println("sleeping...");
Thread.sleep(2000);
System.out.println("out...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void plain() {
System.out.println("plain...");
}
}
Output:
sleeping...
out...
plain...
You should call start() rather than run() on the new Thread. Calling run() will execute the runnable's run method in the current thread, rather than starting a new thread to run it.