16

I have 3 threads 1st printing A 2nd printing B 3rd printing C

I want to print in sequence A B C A B C A B C and so on.....

So I wrote the program below, but I am not able to achieve the same. I am aware of the problem that when status=1 at that time say for example B1 and C1 thread are waiting and when I do notifyAll() both waiting thread wake up and depending on CPU allocation it might print B or C.

in this case I want only B to be printed after A.

what modification I need to do.

public class NotifyAllExample {

    int status=1;
    public static void main(String[] args) {

        NotifyAllExample notifyAllExample = new NotifyAllExample();

        A1 a=new A1(notifyAllExample);
        B1 b=new B1(notifyAllExample);
        C1 c=new C1(notifyAllExample);

        a.start();
        b.start();
        c.start();
    }
}

class A1 extends Thread{
    NotifyAllExample notifyAllExample;

    A1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

                for (int i = 0; i < 100; i++) {

                    if(notifyAllExample.status!=1){
                        notifyAllExample.wait();
                    }

                    System.out.print("A ");
                    notifyAllExample.status = 2;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 1 :"+e.getMessage());
        }

    }

}

class B1 extends Thread{

    NotifyAllExample notifyAllExample;

    B1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

                for (int i = 0; i < 100; i++) {

                    if(notifyAllExample.status!=2){
                        notifyAllExample.wait();
                    }

                    System.out.print("B ");
                    notifyAllExample.status = 3;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 2 :"+e.getMessage());
        }

    }
}


class C1 extends Thread{

    NotifyAllExample notifyAllExample;

    C1(NotifyAllExample notifyAllExample){
        this.notifyAllExample = notifyAllExample;
    }

    @Override
    public void run() {

        try{
            synchronized (notifyAllExample) {

                for (int i = 0; i < 100; i++) {

                    if(notifyAllExample.status!=3){
                        notifyAllExample.wait();
                    }

                    System.out.print("C ");
                    notifyAllExample.status = 1;
                    notifyAllExample.notifyAll();
                }

            }
        }catch (Exception e) {
            System.out.println("Exception 3 :"+e.getMessage());
        }

    }
}
2
  • 1
    AMHO the answers are appropriate but you may optimize this code with instantiation: the three classes are the same except the status literal value. You may add a parameter, I suggest executionOrder, to have only one class. Give a name to the thread with setName() or with super() and use it in the exception reporting. Commented Oct 20, 2012 at 14:43
  • true...I will optimize it....thanks Aubin. Commented Oct 20, 2012 at 14:53

11 Answers 11

14

Convert those IF statements to WHILE statements to get the desired behavior:

if (notifyAllExample.status != 2){
    notifyAllExample.wait();
}

to

while (notifyAllExample.status != 2){
    notifyAllExample.wait();
}

This will ensure that if a thread is notified, it won't go out of the while loop until the status value is what it expects.

Also, mark status as volatile so that the threads won't have a local copy.

Sign up to request clarification or add additional context in comments.

5 Comments

Also, as you mentioned to mark status as volatile how it will benefit me? without marking it as volatile also I am getting desired result. theoretically I know what Volatile do but not practically....can you just explain me how java will treat status variable here without volatile and with volatile?
without volatile keyword on status allows JVM to optimize the access to status variable by having a local copy for each thread which means writes by other threads won't be visible. Specifying the volatile keyword would prevent such optimizations and any read would get to see the value by the most recent write.
as you mention "by having a local copy for each thread which means writes by other threads won't be visible"......if that is the case then every time update done on status variable by Thread A1/B1/C1 should be local to that thread. so when A1 changes status=2 from status=1 that will be local to A1 and B1 still has its local copy set to status=1 and it will always be in waiting state. then how it is going ahead...please clear my doubt.
It is not guaranteed that changes to non-volatile variables are not visible across threads. It is guaranteed that changes to volatile variables are visible across threads. cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile is a good read on why volatile.
thanks...I found some example and after running the program so many times I am able to reproduce problem of without declaring variable as Volatile.
7
 public class RunThreadsInOrder implements Runnable {

    static int numThread = 1;
    static int threadAllowedToRun = 1;
    int myThreadID;
    private static Object myLock = new Object();

    public RunThreadsInOrder() {
        this.myThreadID = numThread++;
        System.out.println("Thread ID:" + myThreadID);
    }

    @Override
    public void run() {
        synchronized (myLock) {
            while (myThreadID != threadAllowedToRun) {
                try {
                    myLock.wait();
                } catch (InterruptedException e) {

                } catch (Exception e) {}
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }

            System.out.println("myThreadID is running: " + myThreadID);
            myLock.notifyAll();
            threadAllowedToRun++;
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Thread t1 = new Thread(new RunThreadsInOrder());
        Thread t2 = new Thread(new RunThreadsInOrder());
        Thread t3 = new Thread(new RunThreadsInOrder());
        Thread t4 = new Thread(new RunThreadsInOrder());
        Thread t5 = new Thread(new RunThreadsInOrder());
        Thread t6 = new Thread(new RunThreadsInOrder());
        Thread t7 = new Thread(new RunThreadsInOrder());

        t7.start();
        t6.start();
        t5.start();
        t4.start();
        t3.start();
        t2.start();
        t1.start();

    }
}

Comments

1
    public class Main {
        public static void main(String[] args) throws IOException{
        Thread t1 = new Thread(new A(), "1");
        Thread t2 = new Thread(new A(), "2");
        Thread t3 = new Thread(new A(), "3");

        t1.start();
        try{
            t1.join();
        }catch (Exception e){

        }
        t2.start();
        try{
            t2.join();
        }catch (Exception e){

        }
        t3.start();
        try{
            t3.join();
        }catch (Exception e){

        }


    }
}

    class A implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName());
    }
}

or you can use Executor Framework

public class Sequence {
    int valve = 1;
    public static void main(String[] args){
        Sequence s = new Sequence();
        ExecutorService es = Executors.newFixedThreadPool(3);

        List<Runnable> rList = new ArrayList<>();
        rList.add(new A(s));
        rList.add(new B(s));
        rList.add(new C(s));

        for(int i = 0; i < rList.size(); i++){
            es.submit(rList.get(i));
        }
        es.shutdown();

    }
}

class A implements Runnable{
    Sequence s;

    A(Sequence s){
        this.s = s;
    }

    public void run(){
        synchronized (s) {
            for (int i = 0; i < 10; i++) {
                while (s.valve != 1) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                s.valve = 2;
                s.notifyAll();
            }
        }
    }
}

class B implements Runnable{
    Sequence s;

    B(Sequence s){
        this.s = s;
    }

    public void run() {
        synchronized (s) {
            for (int i = 0; i < 10; i++) {
                while (s.valve != 2) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                s.valve = 3;
                s.notifyAll();
            }
        }
    }
}

class C implements Runnable{
    Sequence s;

    C(Sequence s){
        this.s = s;
    }

    public void run() {
        synchronized (s) {
            for(int i = 0; i < 10; i++) {
                while (s.valve != 3) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("C");
                s.valve = 1;
                s.notifyAll();
            }
        }
    }
}

In the first case the join for each thread causes the threads to wait for one another. In the second case a list stores the threads and executor executes them one after another creating 3 threads

Another way to do this is where only one runnable class is present and communication between thread is done via static variable in the main class and a variable in the runnable class

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Seq {
    int i = 1;
    public static void main(String[] args){
        Seq s = new Seq();
        Common c1 = new Common(s, 1);
        Common c2 = new Common(s, 2);
        Common c3 = new Common(s, 3);

        List<Runnable> l = new ArrayList<>();
        l.add(c1);
        l.add(c2);
        l.add(c3);

        ExecutorService es = Executors.newFixedThreadPool(3);
        for(int i = 0; i < 3; i++){
            es.submit(l.get(i));
        }
        es.shutdown();
    }
}

class Common implements Runnable{
    Seq s;
    int o;

    Common(Seq s, int o){
        this.s = s;
        this.o = o;
    }

    public void run(){
        synchronized (s) {
            for (int z = 0; z < 100; z++) {
                if(s.i > 3)
                    s.i = 1;
                while (s.i != o) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(o);
                s.i++;
                s.notifyAll();
            }
        }
    }
}

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. - From Review
1

I was asked to write a similar program in an interview with the added condition that it should be extensible in a way that we can provide our own count of threads and they should print characters with the first thread printing 'A' and then the subsequent threads printing B, C, D and so on. Here's how I did it.

public class AlternateCharPrinter {

    public static char ch = 65;

    private static void createAndStartThreads(int count) {
        Object lock = new Object();
        for (int i = 0; i < count; i++) {
            new Thread(new AlternateCharRunner((char) (65 + i), lock)).start();
        }

    }

    public static void main(String[] args) {
        createAndStartThreads(4);
    }

}

class AlternateCharRunner implements Runnable {

    private char ch;
    private Object lock;
    private static int runnerCount;

    public AlternateCharRunner(char ch, Object lock) {
        this.ch = ch;
        this.lock = lock;
        runnerCount++;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (lock) {
                while (ch != AlternateCharPrinter.ch) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(AlternateCharPrinter.ch++);
                if (AlternateCharPrinter.ch == (65 + runnerCount)) {
                    AlternateCharPrinter.ch = 65;
                }
                lock.notifyAll();
            }
        }
    }

}

Comments

0

You need to replace

if (notifyAllExample.status!=1)

with

while (notifyAllExample.status!=1)

and same thing in the other 2 classes. If not, then as soon as the wait exits the thread continues without knowing if it is its turn.

Comments

0

Replace:

if(notifyAllExample.status!=1){
   notifyAllExample.wait();
}

with:

while(notifyAllExample.status!=1){
   notifyAllExample.wait();
}

in all classes accordingly.

Comments

0

The simplest solution to solve this can be following way:

public class PrintInOrder implements Runnable {

private int valueToPrint;
private int id;
private static int turn = 1;
private static int RESET_TURN_THRESHOLD = 3;

public PrintInOrder() {
    this.valueToPrint = -1;
}

public PrintInOrder(int id, int val) {
    this.id = id;
    this.valueToPrint = val;
}

@Override
public void run() {
        while(true) {
            if (turn == this.id) {
                System.out.println(Thread.currentThread().getName() + "::::" + valueToPrint);
                turn++;
            }
            if (turn > RESET_TURN_THRESHOLD) {
                turn = 1;
            }
        }

}

public static void main(String []args) {
    Thread t1 = new Thread(new PrintInOrder(1, 1));
    t1.setName("THREAD-1");
    t1.start();
    Thread t2 = new Thread(new PrintInOrder(2, 2));
    t2.setName("THREAD-2");
    t2.start();
    Thread t3 = new Thread(new PrintInOrder(3, 3));
    t3.setName("THREAD-3");
    t3.start();
}

}

/*
OUTPUT::::
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
...
*/

1 Comment

Why the above solution has printed the the thread sequence 6 times?
0

Here is my solution -

I have created three threads each thread knows what it needs to print and what comes after it.

I have also created a Class NLock which holds the next word which needs to be printed.

Whenever a thread is able to acquire NLock lock then it checks if it's his turn if yes then it prints the word and set the next value to be printed in NLock or else it waits till it's his turn

public class SynchronizeThreeThreads {

    public static void main(String args[]) throws InterruptedException {
        NLock lock=new NLock("A");
        Thread a =new Thread(new PrintInOrder("A","B",lock));
        Thread b =new Thread(new PrintInOrder("B","C",lock));
        Thread c =new Thread(new PrintInOrder("C","A",lock));

        a.start();
        b.start();
        c.start();
        c.join(); // Once all is done main thread will exit
        System.out.println("Done");
    }
}

class NLock{
     private String value;

     public NLock(String value) {
         this.value=value;
     }

     public String getValue() {
         return value;
     }

     public void setValue(String next) {
         this.value=next;
     }

}

class PrintInOrder implements Runnable{

    private String word;

    private String next;

    private NLock lock;

    public PrintInOrder(String word, String next,NLock lock){
        this.word=word;
        this.next=next;
        this.lock=lock;
    }

    @Override
    public void run() {
        int i=0;
        while(i<3) {
            synchronized (lock) {
                try {
                    //Check if it's my turn
                    if(lock.getValue().equals(word)) {
                        System.out.println(this.word);
                        //Set what next needs to be printed
                        //So that when that thread wakes up it knows that it's his turn
                        lock.setValue(next);
                        i++;
                        lock.notifyAll();
                        Thread.sleep(100);
                    }
                    else //Nope not my turn wait
                        lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

Below is the output

A B C A B C A B C Done

Comments

0

This is my attempt to solve the same. Any suggestions are welcome. This is the complete running code.

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class SeqExecution {
    static class SeqThread extends Thread {
        private static final Object lock = new Object();
        private static final AtomicInteger AUTO_COUNTER = new AtomicInteger();
        private static final TrackExecution trackExecution = new TrackExecution();

        private final int seqNo;

        SeqThread(Runnable runnable) {
            super(runnable);
            this.seqNo = AUTO_COUNTER.getAndIncrement();
        }

        @SneakyThrows
        @Override
        public void run() {
            while (true) {
                synchronized (lock) {
                    while (trackExecution.CUR_EXECUTION.get() != this.seqNo) {
                        try {
                            lock.wait(100);
                        } catch (Exception e) {}
                    }

                    //log.info("Thread: {} is running", this.seqNo);
                    super.run();
                    sleep(1000);
                    trackExecution.increment();
                    lock.notifyAll();
                }
            }
        }

        static class TrackExecution {
            private final AtomicInteger CUR_EXECUTION = new AtomicInteger();

            int get() {
                return CUR_EXECUTION.get();
            }

            synchronized void increment() {
                var val = CUR_EXECUTION.incrementAndGet();

                if (val >= SeqThread.AUTO_COUNTER.get()) {
                    CUR_EXECUTION.set(0);
                }
            }

        }
    }

    public static void main(String[] args) {
        final var seqThreads = List.of(new SeqThread(() -> System.out.print("A ")),
            new SeqThread(() -> System.out.print("B ")),
            new SeqThread(() -> System.out.print("C ")));
        seqThreads.forEach(Thread::start);
        seqThreads.forEach(t -> {
            try {
                t.join();
            } catch (Exception e) {
                log.warn(e.getMessage(), e);
            }
        });
    }
}

Comments

-1

I think it's simpler to achieve this using join. Example:

    public static void main(String[] args) {    
    final Thread t1 = new Thread("t1") {
        @Override
        public void run() {
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    final Thread t2 = new Thread(t1, "t2") {
        @Override
        public void run() {
            t1.start();
            try {
                t1.join();
            } catch ( InterruptedException e ) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    Thread t3 = new Thread(t2, "t3") {
        @Override
        public void run() {
            t2.start();
            try {
                t2.join();
            } catch ( InterruptedException e ) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("i am thread: " + Thread.currentThread().getName());
        }
    };

    t3.start();

}

1 Comment

can you please explain how the thread continuously run in a cyclic manner?
-1

Here is my solution please try and let me know

package thread;

class SyncPrinter {
    public static void main(String[] args) {
        SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
        SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
        SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
        SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);

        printAction1.setDependentAction(printAction4);
        printAction2.setDependentAction(printAction1);
        printAction3.setDependentAction(printAction2);
        printAction4.setDependentAction(printAction3);

        new Thread(printAction1, "T1").start();;        
        new Thread(printAction2, "T2").start();
        new Thread(printAction3, "T3").start();     
        new Thread(printAction4, "T4").start();



    }
}

class SyncPrinterAction implements Runnable {

    private volatile boolean dependent;
    private SyncPrinterAction dependentAction;
    int[] data;

    public void setDependentAction(SyncPrinterAction dependentAction){
        this.dependentAction = dependentAction;

    }

    public SyncPrinterAction( int[] data, boolean dependent) {
        this.data = data;
        this.dependent = dependent;
    }

    public SyncPrinterAction( int[] data, SyncPrinterAction dependentAction, boolean dependent) {
        this.dependentAction = dependentAction;
        this.data = data;
        this.dependent = dependent;
    }

    @Override
    public void run() {
        synchronized (this) {

            for (int value : data) {

                try {
                    while(dependentAction.isDependent())
                        //System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
                    wait(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                dependentAction.setDependent(true);

                System.out.println(Thread.currentThread().getName() + " :: " +value);
                dependent = false;
            }

        }

    }

    private void setDependent(boolean dependent) {
        this.dependent = dependent;

    }

    private boolean isDependent() {
        return dependent;
    }

}

2 Comments

Code dump answers are not useful to other readers because they don't explain what you have changed, or what you are trying to demonstrate. Please add explanation.
The idea is very simple: What is the wait condition for each thread?? For thread 2 : 1 thread should executed once before the thread 2 execute once. For thread 3 : 2 thread should executed once before the thread 3 execute once. and so on as many threads are there. For thread 2 : n thread should executed once before the thread 1 execute once. Here is the trick we should initialize as n-thread executed so the 1 - thread will start first then 2 thread and so on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.