-1

Thread 1 prints A1 A2 A3. Thread 2 prints B1 B2 B3. I want to write a program that will make sure when both threads run the output will be A1 B1 A2 B2 A3 B3. So far I have come up with below program. Please let me know how this can be simplified? Can we use less Semaphores? Can this be achieved using wait() notify()?

package com.MultiThreading.threadSerialization;

import java.util.concurrent.Semaphore;

public class ThreadSerialization {

Semaphore a1Done = new Semaphore(0);
Semaphore b1Done = new Semaphore(0);
Semaphore a2Done = new Semaphore(0);
Semaphore b2Done = new Semaphore(0);
Semaphore a3Done = new Semaphore(0);

/**
 * methodA prints : A1 A2 A3
 */
public void methodA() {

    System.out.println("A1");
    a1Done.release();       
    b1Done.acquire();
    System.out.println("A2");
    a2Done.release();
    b2Done.acquire();       
    System.out.println("A3");
    a3Done.release();

}

/**
 * methodB prints : B1 B2 B3 
 */
public void methodB() {
    a1Done.acquire();
    System.out.println("B1");
    b1Done.release();
    a2Done.acquire();
    System.out.println("B2");
    b2Done.release();
    a3Done.acquire();       
    System.out.println("B3");


}

public void createTwoThreads() throws InterruptedException{ 
    ThreadSerialization ts = new ThreadSerialization();
    Thread T1 = new Thread(() -> ts.methodA());
    Thread T2 = new Thread(() -> ts.methodB());
    T1.start();
    T2.start();
    Thread.sleep(5000);
    System.out.println("test done");
}

}

AmolB
  • 149
  • 6
  • Removed try catch for readability, though it won't compile without it. – AmolB Jan 12 '18 at 18:33
  • Wrong approach. Please dont put up "not compiling" code. When people tell you: "your code is doing things the wrong way" - then ask how to fix that. And then fix it. Dont just blindly remove code. People will quickly jump on you for putting up not-compiling code. – GhostCat Jan 12 '18 at 18:43
  • Wasn't even that unclear in the first place, that's just Java boilerplate. –  Jan 12 '18 at 19:09
  • 1
    To get it to compile, enclose the body of each method in *one* try/catch block. An interrupt is an explicit request for your thread to stop whatever it’s doing and exit gracefully. You should never ignore InterruptedExceptions and continue as if nothing happened; doing so makes your thread a rogue thread that cannot be terminated cleanly. – VGR Jan 12 '18 at 19:21
  • @xTrollxDudex It was needlessly unclear and represented code that should either `throws` and/or wrapped at a higher level. Java doesn't force one to write code more complicated than Java requires.. just because Java IDEs want to "autowrap" checked exceptions doesn't mean they should be blindly honored :} I would have rejected such code under a review and it's extra important on SO where code in questions is judged much more quickly.. – user2864740 Jan 12 '18 at 21:27

2 Answers2

-1

You can use two semaphore if you ensure that will only one thread executing methodA and another thread for methodB. When you print A1, you give T2 the posibility to print B1. Then it will need to wait for A2 to be printed to continue

  Semaphore aPrintDone = new Semaphore(0);
  Semaphore bPrintDone= new Semaphore(0);

/**
 * methodA prints : A1 A2 A3
 */
 public void methodA() {
     try {
         System.out.println("A1");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A2");
         aPrintDone.release();
         bPrintDone.acquire();
         System.out.println("A3");
         aPrintDone.release();
    }catch (InterruptedException e1) {
         e1.printStackTrace();
    }
  }

  /**
   * methodB prints : B1 B2 B3 
  */
  public void methodB() {
    try {
        aPrintDone.acquire();
        System.out.println("B1");
        bPrintDone.release();
        aPrintDone.acquire();
        System.out.println("B2");
        bPrintDone.release();
        System.out.println("B3");
    }catch (InterruptedException e1) {
        e1.printStackTrace();
    }
}

This problem could also be resolved using wait() and notify(). Consider that wait() means that the thread will be waiting until a certain condition is met (in this case the B printing, for T1; and the A printing for thread T2). So when the System.out.println is done, it could notify() the other thread to start printing. I prefer the semaphore resolution, but it´s ok to solve it using those methods.

Santiago Salem
  • 577
  • 2
  • 12
-1

To answer the wait-notify question: Yes, it is possible. It even works with only one lock-object. But the code is neither very readable nor "secure". The code requires, that methodA() is executed before methodB(), otherwise the program will deadlock.

public class Synchronization {

    synchronized public void methodA() {
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("A3");
        this.notify();
    }

    synchronized public void methodB() {
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B1");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B2");
        this.notify();

        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B3");
    }

    public static void main(String... args) throws InterruptedException {
        Synchronization ts = new Synchronization();
        Thread t1 = new Thread(ts::methodA);
        Thread t2 = new Thread(ts::methodB);

        t1.start(); // If you switch those lines,
        t2.start(); // the program will deadlock.

        t1.join();
        t2.join();
        System.out.println("test done");
    }
}
Turing85
  • 18,217
  • 7
  • 33
  • 58
  • If methodA executes first, the program will stuck because T1 will wait forever. – AmolB Jan 13 '18 at 05:04
  • @AmolBinwade the first `wait()` in `methodA()` is released by the immediate `notify()` in `methodB()`. Can you please specify at which `wait()` you have seen a deadlock in `method1()`? – Turing85 Jan 13 '18 at 09:28
  • Right..i missed that...this should work...will give it a try and confirm. Thanks. – AmolB Jan 13 '18 at 22:18
  • .But the sequence t1.start() before t2.start() doesn't guarantee that methodA will start execution before methodB. Its upto the scheduler which thread it will start executing first. Right? – AmolB Jan 13 '18 at 22:24
  • That is true. this is why I explicitly said in my answer that `methodA()` has to be called before `methodB()`. You can enforcde the order through, e.g., a `CountDownLatch`. – Turing85 Jan 14 '18 at 01:32