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.
Related
I observed a scenario where use of synchronized method or synchronized block producing different results.
From below code:
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("]");
}
}
class Caller implements Runnable{
String msg;
Callme target;
Thread t;
public Caller(Callme target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread(this, "Caller thread");
t.start();
}
#Override
public void run() {
synchronized(target) {
target.call(msg);
new Callme().call(msg);
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
Callme obj = new Callme();
new Caller(obj, "thread1");
new Caller(obj, "thread2");
new Caller(obj, "thread3");
Thread.currentThread().join();
}
}
When I use the synchronized block in the Caller::run method the ouput is synchronized as below:
[thread1]
[thread1]
[thread3]
[thread3]
[thread2]
[thread2]
But when I use the synchronized method for the Callme::call method, instead of synchronized block, the output is not synchronized:
[thread1]
[thread1[thread2]
]
[thread3[thread2]
]
[thread3]
My Expectation is the output should not be synchronized on both cases because I am using different objects when calling the "Callme::call" method
This made me question my understanding of the Synchronized block concept?
A synchronized method is equivalent to a synchronized(this)-block for the length of the entire method, however your code is using synchronized(target), and target is a shared instance of Callme. In other words: the object being synchronized on is different, so the behavior is not the same.
In the case you use synchronized(target), it means that all threads synchronize on the same instance of Callme so their behavior is serial: a thread will hold the monitor of that Callme instance for the whole duration of the Caller.run method, so in effect the threads are executed one after the other.
In the case of a synchronized method, the threads each synchronize on their own instance of Caller, so in effect there is no serialization (except for the writes to System.out).
Some additional remarks:
Calling Thread.currentThread().join() is a bad idea, because it will wait on itself
In general don't create and start Thread instances in the Runnable implementation that is going to be run by that thread: you lose access to the thread. Especially don't do this in the constructor, because you are publishing a partially constructed object to the Thread, which is not a big problem in this code, but might lead to subtle bugs in more complex applications.
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.
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!");
}
with code such as
synchronized (this)
{
mTimeOutRunnable = new Runnable()
{
#Override
public void run()
{
..some code
}
};
}
the reference assignement of the new Runnable class is covered by the block but will code inside run() (which is asyncronously called outside of the block) enter into the synchronized block also?
I wrapped in the sync block in the first place as this is called from a worker thread and I want to ensure the calling (main) thread has access to the mTimeOutRunnable object also.
No, only the assignment of your Runnable to mTimeOutRunnable is covered by the synchronized block, not subsequent calls to the run() method.
mTimeOutRunnable = new Runnable()
{
#Override
public void run()
{
..some code
}
};
is same as
synchronized(this){
obj = new SomeClass();
}
So only the reference assignment is covered by synchronized block