Can anyone please explain what happens to data members while threading? I mean in the below code the output is as I wanted i.e thread name with its corresponding number.However if I pass the reference of 1 thread to all the other threads the thread name varies but the number 50 is printed for all the thread names.Why does this happen?
class Thread3 implements Runnable
{
int x;
public void run()
{
for(int i=1;i<=5;i++)
{
System.out.println(Thread.currentThread().getName()+" "+ x);
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}
public class RunThread3 {
public static void main(String s[])
{
Thread3 t1=new Thread3();
t1.x=50;
Thread tt1=new Thread(t1,"thread1");
tt1.start();
Thread3 t2=new Thread3();
t2.x=100;
Thread tt2=new Thread(t2,"thread2");
tt2.start();
Thread3 t3=new Thread3();
t3.x=150;
Thread tt3=new Thread(t3,"thread3");
tt3.start();
for(int i=1;i<=5;i++)
{
System.out.println(Thread.currentThread().getName());
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}
Here reference of 1 thread passed to all others
class Thread3 implements Runnable
{
int x;
public void run()
{
for(int i=1;i<=5;i++)
{
System.out.println(Thread.currentThread().getName()+" "+ x);
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}
public class RunThread3 {
public static void main(String s[])
{
Thread3 t1=new Thread3();
t1.x=50;
Thread tt1=new Thread(t1,"thread1");
tt1.start();
Thread3 t2=new Thread3();
t2.x=100;
Thread tt2=new Thread(t1,"thread2");
tt2.start();
Thread3 t3=new Thread3();
t3.x=150;
Thread tt3=new Thread(t1,"thread3");
tt3.start();
for(int i=1;i<=5;i++)
{
System.out.println(Thread.currentThread().getName());
try{
Thread.sleep(1000);
}catch(Exception e){ }
}
}
}
In the later code you are passing reference of thread t1 to all:
Thread3 t1=new Thread3();
t1.x=50;
Thread tt1=new Thread(t1,"thread1");
tt1.start();
Thread tt2=new Thread(t1,"thread2");
tt2.start();
Thread tt3=new Thread(t1,"thread3");
tt3.start();
This means all thread will be having value of x as 50 and when you execute the code you will get the expected value:
thread1 50
thread2 50
main
thread3 50
main
thread1 50
thread3 50
thread2 50
thread1 50
main
thread3 50
thread2 50
thread3 50
main
thread2 50
thread1 50
main
thread3 50
thread2 50
thread1 50
In the former case you are having different threads and they work accordingly.
It is your misunderstanding of threading and classes in java.
In your code you have 2 different entities: java Thread and your custom Runnable class.
Name of thread that you got in your sample is name of java Thread object. Number x that you got in your sample is number of your custom Runnable class. Please note: I skipped name of your class - it makes misunderstanding. So if you use only one your custom Runnable object - you'll always got single x value.
Related
This question already has answers here:
What's the difference between Thread start() and Runnable run()
(14 answers)
Closed 7 years ago.
Consider this simple try for a multithreading example :
public class LetsMutexThreads {
public static Object MUTEX = new Object();
private static class Thread1 extends Thread {
public void run() {
synchronized (MUTEX)
{
System.out.println("I'm thread 1 , goint to take a nap...");
try
{
MUTEX.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("T1 : That's it , I'm done ...");
}
}
}
private static class Thread2 extends Thread {
public void run() {
synchronized (MUTEX)
{
System.out.println("Thread 2 : Let's rock N roll !");
System.out.println("Waking up my buddy T1 ...");
MUTEX.notify();
}
}
}
public static void main(String[] args)
{
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.run();
t2.run();
}
}
I'm trying to allow Thread1 to go to sleep with the wait , and then let Thread2
to use notify() to wake Thread1 , but he doesn't get a chance .
Why does the wait() of Thread1 affects the Main Thread from executing t2.run(); ?
You must not attempt to start a thread using the run() method. It does not actually create a new thread, it runs the code in the current thread. Use thread.start() instead in order to have your code executed in a separate (new) thread
This is wrong:
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.run();
t2.run();
Change it to this:
Thread2 t2 = new Thread2();
Thread1 t1 = new Thread1();
t1.start();
t2.start();
I was asked to created a dead lock situation. Below code is never creating me dead lock although there is a chance of getting dead lock.
The reason is as follows.
If method1() and method2() both will be called by two or many threads , there is a good chance of deadlock because if thead 1 aquires lock on Sting object while executing method1() and thread 2 acquires lock on Integer object while executing method2() both will be waiting for each other to release lock on Integer and String to proceed further which will never happen.
I wanted to create a dead lock situation but is not creating it.
class Task implements Runnable {
public void method1() {
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
}
}
}
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
#Override
public void run() {
method1();
method2();
}
}
public class DeadLock {
public static void main(String args[]) {
Runnable r= new Task();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
If you want to increase the chance for deadlock, you can sleep the thread after it acquires the first lock, and before it tries to acquires the second lock. One rough example:
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
synchronized (String.class) {
System.out.println("Thread 1 after acquiring String lock");
Thread.sleep(5000); // Sleep for 5 seconds
synchronized (Integer.class) {
System.out.println("Thread 1 after acquiring Integer lock");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
synchronized (Integer.class) {
System.out.println("Thread 2 after acquiring Integer lock");
Thread.sleep(5000); // Sleep for 5 seconds
synchronized (String.class) {
System.out.println("Thread 2 after acquiring String lock");
}
}
}
});
t1.start();
t2.start();
}
You will see:
Thread 1 after acquiring String lock
Thread 2 after acquiring Integer lock
or
Thread 2 after acquiring Integer lock
Thread 1 after acquiring String lock
and then deadlock happens.
This is unlikely create a deadlock, as the Task always attempts method1 then method2. You need to have 2 different runnables which call method1 and method2 in opposing orders. Additionally, you probably should consider using a countdown latch that your tasks must wait for at the beginning of run() to provide a higher probability of the 2 threads actually executing concurrently.
I am trying to implementing deadlock condition but somehow I am not able to get it working. Both the threads Thread1 and Thread2 are entering in the run function but only one of them enters in Sub/Sum depending on who entered run first. Example : if Thread2 entered run first the it will call sub() and Thread1 never calls sum(). I have also added sleep time so that Thread2 sleeps before calling sum() and Thread1 gets enough time to enter Sum() but Thread1 never enters.
public class ExploringThreads {
public static void main(String[] args) {
// TODO Auto-generated method stub
threadexample a1 = new threadexample();
Thread t1 = new Thread(a1, "Thread1");
Thread t2 = new Thread(a1,"Thread2");
t1.start();
t2.start();
}
}
class threadexample implements Runnable{
public int a = 10;
public void run(){
if(Thread.currentThread().getName().equals("Thread1"))
sum();
else if(Thread.currentThread().getName().equals("Thread2"))
sub();
}
public synchronized void sum()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sum");
sub();
}
public synchronized void sub()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sub");
sum();
}
}
If you really want to create an artificial dead lock, try this:
Thread1 and Thread2 are two threads that want to access the same file.
Thread1 starts, asks for a lock on File1.docx and sleeps for 2 minutes.
Thread2 starts, and makes an exclusive lock on File2.docx and now wants to access File1.docx.
Thread1 wakes up and now wants to access File2.docx which is held by Thread2
Now, this is a circular wait condition
Simple ? =)
This is not how you get a deadlock. Actually this code seems pretty safe :-) Only one thread enters sum/sub at a time because you are using synchronized which synchronizes on "this". There is only one "this" so both threads try to acquire the same lock.
Deadlock occurs, for instance, when Thread1 has one lock, Thread2 has second lock and then Thread1 would like to acquire Thread2's lock while still holding it's lock and Thread2 would like to acquire Thread1's lock while still holding it's lock.
What you could do is:
a) add 2 objects for locking in "threadexample" class (btw classes by convention should start with uppercase):
private final Object sumLock = new Object();
private final Object subLock = new Object();
b) drop the "synchronized" keyword in both sum/sub methods and instead use the synchronized() {} block in each of them. Sum would be synchronized(sumLock) { /* sum's body goes here / } and sub would be synchronized(subLock) { / sub's body goes here */}.
In this case Thread1 would go into sum(), acquire the sumLock and wait. Thread2 would go into sub(), acquire the subLock() and wait. Thread1 would wake up, go into sub() and try to acquire subLock but it's being held by Thread2 so it wait's until Thread2 releases it. In that time Thread2 wakes up, goes into sum() and tries to acquire sumLock which is held by Thread1 so Thread2 waits for Thread1 to release it.
Neither thread will go forward as each one of them is waiting for the other - you have a deadlock.
#Edit: yes you have only 1 instance of "threadexample" and both Thread1 and Thread2 are fighting for the lock but when one of them acquires the lock it will release it after executing sum/sub or sub/sum. For instance let's say Thread1 is first and starts executing sum(). It has the lock. In that case Thread2 will not go into sub() as it is protected by the same lock as Thread1. Thread1 will do sum(), then sub() and then it will release the lock --> Thread2 will go into sub() etc.
This is a working example of 'Deadlock in Action'. Basically what you need to do (and how that usually happens in real world) is that object are locked in opposite order: a first, b second in one thread and b first, a second in another:
package stackoverflow;
public class Deadlock {
final static String a = new String("A");
final static String b = new String("B");
public static void main(String[] args) {
final Thread abLock = new Thread() {
#Override
public void run() {
lock(a, b);
}
};
final Thread baLock = new Thread() {
#Override
public void run() {
lock(b, a);
}
};
abLock.start();
baLock.start();
}
static void lock(String first, String second) {
synchronized (first) {
System.out.println(first);
sleep();
synchronized (second) {
System.out.println(second);
}
}
}
static void sleep() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Here is a code i am having problem with --
public class WaitTest {
public static void main(String[] args) {
Runner rr = new Runner();
Thread t1 = new Thread(rr,"T1");
Thread t2 = new Thread(rr,"T2");
t1.start();
t2.start();
}
}
class Runner implements Runnable{
int i=0;
public void run(){
try{
if(Thread.currentThread().getName().equals("T1")){
bMethod();
aMethod();
}
else{
aMethod();
bMethod();
}
}catch(Exception e){}
}
public synchronized void aMethod() throws Exception{
System.out.println("i="+i+",Now going to Wait in aMethod "+Thread.currentThread().getName());
Thread.currentThread().wait();
System.out.println("Exiting aMethod "+Thread.currentThread().getName());
}
public synchronized void bMethod() throws Exception{
System.out.println("i="+i+",Now going to Wait bMethod "+Thread.currentThread().getName());
i=5;
notifyAll();
System.out.println("Exiting bMethod "+Thread.currentThread().getName());
}
}
The output is :
i=0,Now going to Wait bMethod T1
Exiting bMethod T1
i=5,Now going to Wait in aMethod T1
i=5,Now going to Wait in aMethod T2
My question is :
Why T2 enters in aMethod while T1 is waiting inside? and Why T2 prints
i=5 in aMethod.
When you execute wait, your thread releases the lock and enters the wait state. At this time the other thread is allowed to enter the method. You are using a single instance of Runnable so when one thread sets it to 5, that's what the other thread reads.
1. wait will immediately release the lock, and handover the lock to the other thread.
2. notify will release the lock only when the closing parenthesis of the synchronized block
is reached.
3. As there is only one instance of Runnable here, its after the i = 5, and when the synchronized block ends..then the lock is released.
This code is not doing the wait-notify pattern. The Thread.currentThread().wait() call throws an IllegalMonitorStateException, which is caught and ignored by the run method. Both T1 and T2 throws this exception, and hence you do not see the line Exiting aMethod printed.
The notify call in bMethod is wasted, because no thread ever waits on the intrinsic lock of the rr Runnable.
I have developed a program in which the thread A waits for Thread B to complete it task and when thread B finishes its task it makes notfiy() to thread A to continue onwards..below is the code..
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.totals);
}
}
}
class ThreadB extends Thread {
public int totals;
public void run() {
synchronized(this) { //instance level lock
for(int i=0;i<100;i++) {
totals += i;
}
notify();
}
}
}
Now I want lets say 3 more thread are waiting for thread b , so please advise me how to spawn 3 more threads , just like thread A is waiting , please advise.
Use the ExecutorService it has a methode invokeAll(). You can submit all your ThreadB and hold a List of Future's.
Your current code actually contain possible deadlock since you start() the threadB first and it is calling the notify() in its run(). This notify() is possible to be called before the wait() in the main. If this happens, you threadB will be waiting forever.
To start more ThreadB, you just need to create more instances.
ThreadB threadBs = new ThreadB[3];
for (ThreadB b : threadBs) {
b = new ThreadB();
b.start();
}
However, I will suggest implementing the Runnable interface instead of just extending the Thread class.