running 3 threads in sequence java

别来无恙 提交于 2019-11-27 01:12:35

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.

Manoj Saxena
 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();

    }
}

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();
            }
        }
    }

}

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.

Replace:

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

with:

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

in all classes accordingly.

    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();
            }
        }
    }
}

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
...
*/

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();

}

Visu

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;
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!