Run Java Threads sequentially

2019-01-07 22:45发布

问题:

How will you execute Three threads sequentially? For eg. Thread1, Thread2, Thread3. It is not possible to pass the reference of one Thread to the other and invoke from the run() method.

So code should be like this:

 Thread1.start();
 Thread2.start();
 Thread3.start();

and out put should be

 Printing Thread1
 Printing Thread2
 Printing Thread3

This can be possible by using ThreadPoolExecutor and using a blocking queue but even that is not an acceptable answer.

回答1:

Use ExecutorService in java.util.concurrent package. More precisely use Executors.newSingleThreadExecutor();



回答2:

You could use Executors.newSingleThreadExecutor(), but strictly speaking this launches only one Thread, so may not be expected solution.

The simpliest solution using just Thread class:

Thread1.start();
Thread1.join();
Thread2.start();
Thread2.join();
Thread3.start();
Thread3.join();

(I omitted exception handling for clarity, Thread.join() can throw InterruptedException)



回答3:

The simplest answer is

Thread1.run();
Thread2.run();
Thread3.run();

The problem with unrealistic questions is they often have an uninformative answer. ;)

The whole point of having threads is to run them concurrently. If you are not doing that at all, don't use threads.

You might say that; you cannot call the run() method, in which case you cannot use ThreadPoolExecutor because it calls the run() method for you. i.e. thats what submit() eventually does.

EDIT: The results are completely deterministic, becaus ethe fact that there is a Thread involved is irrelivent.

static class PrintThread extends Thread {
    public PrintThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++)
            System.out.println(getName() + ": " + i);
    }
}

public static void main(String args[]) {
    Thread thread1 = new PrintThread("A");
    Thread thread2 = new PrintThread("B");
    Thread thread3 = new PrintThread("C");

    thread1.run();
    thread2.run();
    thread3.run();
}

Prints

A: 0
A: 1
.. deleted ..
C: 98
C: 99

as expected.



回答4:

Since this is an interview question, they're looking for specific knowledge, not a "well it's obviously better to do it this way" answer. It also seems that they'll likely strike out solution after solution until they get the answer they want.

Odds are they want to see if you can implement inter-thread communications yourself. But they don't want you to do it the easy way (thread references available). Otherwise, you could just do thread.join().

So have all three threads grab some bit of shared memory (synchronized static class). Have each thread check a public static int nextThread(). Upon successful comparison that they are the next thread, they should do their work and update public static setNextThread(int value) with the value of the next thread to be processed.

The key is to do this in a thread-safe manner; however, if you can guarantee unique thread identifiers and ensure that no two threads have the same identifier, you can (with careful coding) even manage to do this without synchronization.



回答5:

If it were not related to various ways of invoking these threads, theoretically, they should use acquire a common sempahore, and release it when done printing.
JDK has an inbuilt semaphore.



回答6:

Threads can be executed sequentially by using ExecutorService. Find below example.

public class SeqThread {

    public static void main(String[] arg) {
          new SeqThread().execute();
    }

    public void execute() {
        try {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        executor.submit(R);
        executor.submit(R2);
        executor.shutdown();

            executor.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    Runnable R = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            for(int i=0;i<10;i++)
            {
                System.out.println("In Thread One "+i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };

    Runnable R2 = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            for(int i=0;i<10;i++)
            {
                System.out.println("In Thread Two="+i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };
}


回答7:

Forcing threads to run in ordered manner is like killing the very concept of multithreading, its more like single threaded program' sub-routine execution. As its interview question so everything is OK. Here is the program that test the logic not with 4 but 50 threads-

public class Outer {
    private Thread[] jobs;
    private String[] names;
    private int indx;

public Outer(int numOfThreads) {
    jobs = new Thread[numOfThreads];
    names = new String[numOfThreads];
    indx = numOfThreads - 1;
}

class Inner implements Runnable {
public void run() {
    while (true) {
       if (names[indx].equals(Thread.currentThread().getName())) {
          indx--;
          break;
       }
       else {
          try { Thread.sleep(20); } catch(InterruptedException ie) {}
       }
    }
    // now current thread will join behind the previous one..
    if (indx >= 0) try { jobs[indx].join(); } catch(InterruptedException ie) {}

    /***** YOUR ACTUAL CODE GOES FROM HERE *****/

    // at last check is it working ?
    System.out.println(Thread.currentThread().getName());
  }
}

public void f() {
    Inner target = new Inner();
    // initializing all threads..
    for (int i = 0; i < jobs.length; jobs[i++] = new Thread(target));
    for (int i = 0; i < names.length; names[i] = jobs[i++].getName());

    // checking name of threads..
    for (int i = 0; i < names.length; System.out.println(names[i++]));

    System.out.println();

    // now we start all threads..
    for (int i = 0; i < jobs.length; jobs[i++].start());
  }

public static void main(String[] args) {
    new Outer(50).f();               // testing logic not with 4 but 50 threads..
  }
}


回答8:

You can find everything there: http://download.oracle.com/javase/tutorial/essential/concurrency/index.html

Especially read about notifications and synchronization between threads.

P.S. And remember, even if you pass the interview you'll still had to work! :)

(Ok, I'll give some hints: look the description of such methods as Object.wait() and Object.notifyAll() it is the simpliest but also very usefull mechanism)



回答9:

newSingleThreadExecutor. A single-threaded executor creates a single worker thread to process tasks, replacing it if it dies unexpectedly. Tasks are guaranteed to be processed sequentially according to the order imposed by the task queue (FIFO, LIFO, priority order).



回答10:

This could be a trick question. Maybe they don't want to hear the solution to this specific problem but want you to back track to the source of the problem and come up with a better solution.



回答11:

I've used basic thread communication model and it could be more simplified as well. Let's say you have 3 threads, one is printing 0, second one is printing odd number and third one is printing even number liker this 01 02 03 04 05....

public class app{
        int status=0;
        public static void main(String[] args) throws InterruptedException{

            app obj = new app();
            Thread t1 = new Thread(new print(obj,0));
            Thread t2 = new Thread(new print(obj,1));
            Thread t3 = new Thread(new print(obj,2));
                t1.start();t2.start();t3.start();
            }

    }
    class print implements Runnable{
        app obj;
        int a;
        public print(app obj, int a) {
            this.obj=obj;
            this.a=a;
        }
        @Override
        public void run() {
            try{

                if(a==0){
                    synchronized(obj){
                    for (int i = 0; i < 21; i++) {
                        while(obj.status!=0 && obj.status!=3){
                            obj.wait();
                            } 

                        System.out.print(0);
                        if(obj.status==0)//even sets status to 0 so next one is odd
                            obj.status=1;
                        else//odd sets status to 3 so next one is even
                            obj.status=2;
                        obj.notifyAll();
                        }
                    }
                }
                    else if(a%2!=0){
                        synchronized (obj) {
                            for (int i = 0; i < 11; i++) {
                                while(obj.status!=1){
                                    obj.wait();
                                    } 

                                System.out.print(a);
                                a+=2;
                                obj.status=3;
                       //3 decides 0 came after odd, so next one           
                      //after zero is even
                                obj.notifyAll();
                            }
                        }
                    }
                    else{
                        synchronized (obj) {
                            for (int i = 0; i < 11; i++) {
                                while(obj.status!=2){
                                    obj.wait();
                                    } 

                                System.out.print(a);
                                a+=2;
                                obj.status=0;
                                obj.notifyAll();
                            }
                        }
                    }
                }




            catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                }
            }
        }


回答12:

public static void main(String[] args)throws InterruptedException {

    MyRunnable r = new MyRunnable();
    Thread t1 = new Thread(r,"A");
    Thread t2 = new Thread(r,"B");
    Thread t3 = new Thread(r,"C");
    t1.start();
    Thread.sleep(1000);
    t2.start();
    Thread.sleep(1000);
    t3.start();



}