Home > Blockchain >  Java Multithreading: Make threads execute alternatively
Java Multithreading: Make threads execute alternatively

Time:07-23

I am completely new to multi threading. Need assistance on the below scenario

Scenario:- I want two threads to execute, such that they have to print the word "PingPong" alternatively. This has to happen three 3 times for both threads.

For example:-

  1. Thread 1 has to print "Ping" and it has to go to wait stage.
  2. Thread 2 has to print "Ping" and it has to go to wait stage as well as notify the other thread.
  3. Thread 1 has to print "Pong" and it has to go to wait stage as well as notify the other thread.
  4. Thread 2 has to print "Pong" and it has to go to wait stage as well as notify the other thread.

The same way both the threads has to print the word 3 times in total.

Coding below:-

package com.test.files;

public class MultiThreadingTest2 implements Runnable {
    String lastExecutedThread = "";
    Object lockObj = new Object();
    private void print(String wordToPrint) throws InterruptedException {
        synchronized(lockObj) {
            if(lastExecutedThread.equals(Thread.currentThread().getName())) {
                System.out.println(Thread.currentThread().getName() " entered wait stage");
                lockObj.wait();
            } else {
                lastExecutedThread = Thread.currentThread().getName();
                System.out.println(Thread.currentThread().getName() " printed " wordToPrint);
                lockObj.notifyAll();
            }
        }
    }
    
    public MultiThreadingTest2(Object lock) {
        this.lockObj = lock;
    }
    
    @Override
    public void run() {
        String[] wordArr = {"Ping", "Pong"};
        
        for(int i = 0; i < 3; i  ) {
            for(int j = 0; j < wordArr.length; j  ) {
                try {
                    print(wordArr[j]);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        
        Thread t1 = new Thread(new MultiThreadingTest2(lock), "Thread 1");
        Thread t2 = new Thread(new MultiThreadingTest2(lock), "Thread 2");
    
        t1.start();
        t2.start();
    }
}

But I could see the above code has resulted in deadlock. Output as follow:-

Thread 1 printed Ping
Thread 1 entered wait stage
Thread 2 printed Ping
Thread 2 entered wait stage
Thread 1 entered wait stage

I am not sure why this has resulted in deadlock. Reason because, the variable "lastExecutedThread " is created at class level. So it should be stored in heap. If its a local variable, then we can say that it could be in thread stack, so the other thread may not what value it possess and because of which the thread executing the print function will have the "lastExecutedThread" to its name and it will lead to deadlock.

Could you please help on this.

CodePudding user response:

You have to make lastExecutedThread static, otherwise each Thread sees its own instance of it.

Note that if inside the print method lockObj.wait() is called, the wordToPrint passed to this method is never printed. You can slightly adapt your code to avoid this: if your print method returns true if printing was successful, and false otherwise. Then inside your nested for-loop, put your call of print inside a while-loop: while (!print(wordArr[j]));

  • Related