12

你将如何顺序执行三个线程?例如。线程 1、线程 2、线程 3。不可能将一个线程的引用传递给另一个线程并从 run() 方法调用。

所以代码应该是这样的:

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

输出应该是

 Printing Thread1
 Printing Thread2
 Printing Thread3

这可以通过使用 ThreadPoolExecutor 和使用阻塞队列来实现,但即使这样也不是一个可接受的答案。

4

13 回答 13

16

您可以使用Executors.newSingleThreadExecutor(),但严格来说这只会启动一个 Thread,因此可能不是预期的解决方案。

仅使用类的最简单解决方案Thread

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

(为了清楚起见,我省略了异常处理,Thread.join()可以抛出InterruptedException

于 2011-03-28T15:54:27.313 回答
11

最简单的答案是

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

不切实际的问题的问题是他们通常有一个没有信息的答案。;)

拥有线程的全部意义在于同时运行它们。如果您根本不这样做,请不要使用线程。

你可能会这么说;你不能调用 run() 方法,在这种情况下你不能使用 ThreadPoolExecutor 因为它会为你调用 run() 方法。即这就是 submit() 最终所做的。

编辑:结果是完全确定的,因为涉及线程的事实是无关紧要的。

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

印刷

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

正如预期的那样。

于 2011-03-28T15:48:15.217 回答
11

使用java.util.concurrent 包中的ExecutorService。更精确地使用Executors.newSingleThreadExecutor();

于 2011-03-28T15:49:00.990 回答
5

由于这是一个面试问题,他们正在寻找具体的知识,而不是“这样做显然更好”的答案。似乎他们可能会在一个又一个解决方案中找出解决方案,直到他们得到他们想要的答案。

他们很可能想看看您是否可以自己实现线程间通信。但是他们不希望您以简单的方式进行操作(可用的线程引用)。否则,你可以这样做thread.join()

所以让所有三个线程都获取一些共享内存(同步静态类)。让每个线程检查一个public static int nextThread(). 在成功比较它们是下一个线程后,它们应该完成工作并public static setNextThread(int value)使用要处理的下一个线程的值进行更新。

关键是以线程安全的方式执行此操作;但是,如果您可以保证唯一的线程标识符并确保没有两个线程具有相同的标识符,您甚至可以(通过仔细编码)在不同步的情况下做到这一点。

于 2011-03-28T16:08:59.087 回答
5

可以使用 ExecutorService 顺序执行线程。找到下面的例子。

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();
                }
            }
        }
    };
}
于 2013-08-05T12:28:19.587 回答
4

如果与调用这些线程的各种方式无关,理论上应该使用获取一个共同的信号量,打印完成后释放。
JDK 有一个内置的信号量

于 2011-03-28T16:13:12.047 回答
2

强制线程有序运行就像是扼杀了多线程的概念,它更像是单线程程序的子程序执行。作为它的面试问题,一切都很好。这是用 50 个线程而不是 4 个线程测试逻辑的程序 -

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..
  }
}
于 2016-03-05T16:10:54.430 回答
1

您可以在那里找到所有内容:http: //download.oracle.com/javase/tutorial/essential/concurrency/index.html

特别是阅读有关线程之间的通知和同步的信息。

PS 请记住,即使您通过了面试,您仍然需要工作!:)

(好吧,我会给出一些提示:看看这些方法的描述,Object.wait()Object.notifyAll()是最简单但也非常有用的机制)

于 2011-03-28T15:47:55.780 回答
1

新的单线程执行器。单线程执行器创建一个工作线程来处理任务,如果它意外死亡,则替换它。任务保证按照任务队列强加的顺序(FIFO、LIFO、优先级顺序)顺序处理。

于 2011-08-07T16:44:12.233 回答
0

这可能是一个棘手的问题。也许他们不想听到这个特定问题的解决方案,而是希望您回溯到问题的根源并提出更好的解决方案。

于 2011-03-28T17:05:40.563 回答
0

我使用了基本的线程通信模型,它也可以更加简化。假设您有 3 个线程,一个打印 0,第二个打印奇数,第三个打印偶数,例如 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();
                }
            }
        }
于 2016-12-11T19:47:34.073 回答
0

我不确定我是否完全理解了这个问题,但这似乎是我们想要按顺序打印线程的情况。一个示例是使用线程按如下顺序打印值:

线程 - 0 输出:1

线程 - 1 个输出:2

线程 - 2 输出:3

线程 - 0 输出:4

线程 - 1 个输出:5

线程 - 2 输出:6 等等..

如果这是要求,则可以编写用于 n 个线程的通用解决方案,其中每个线程将等待轮到它(使用它将尝试获取锁定的公共对象)。

class ResourceLock {
    private volatile int currentThreadId;
    private final int totalThreads;

    public ResourceLock(int threadsCount) {
        this.currentThreadId = 0;
        this.totalThreads = threadsCount;
    }
    public void assignTokenToNextThread(int currentThreadNum) {
        this.currentThreadId = (currentThreadNum + 1) % totalThreads;
    }
    public int getCurrentThreadId() {
        return currentThreadId;
    }
}

现在工作线程将完成其工作并使用上述类的实例进行锁定:

class Worker extends Thread {
    private final ResourceLock resourceLock;
    private final int threadId;                     // id of this thread
    private final AtomicInteger counter;            // counter shared by all threads, will print number in sequence.
    private volatile boolean running = true;        // flag to stop this thread when necessary
    public Worker(ResourceLock resourceLock, int threadNumber, AtomicInteger counter) {
        this.resourceLock = resourceLock;
        this.threadId = threadNumber;
        this.counter = counter;
    }
    @Override
    public void run() {
        while (running) {
            try {
                synchronized (resourceLock) {
                    while (resourceLock.getCurrentThreadId() != this.threadId) {
                        resourceLock.wait();
                    }
                    System.out.println("Thread:" + threadId + " value: " + counter.incrementAndGet());
                    Thread.sleep(1000);
                    resourceLock.assignTokenToNextThread(this.threadId);
                    resourceLock.notifyAll();
                }
            } catch (Exception e) {
                System.out.println("Exception: " + e);
            }
        }
    }
    public void shutdown() {
        running = false;
    }
}

这可以测试为:

public static void main(String[] args) throws InterruptedException {
        final int threadsCount = 3;
        final ResourceLock lock = new ResourceLock(threadsCount);
        Worker[] threads = new Worker[threadsCount];
        final AtomicInteger counter = new AtomicInteger(0);
        for(int i=0; i<threadsCount; i++) {
            threads[i] = new Worker(lock, i, counter);
            threads[i].start();
        }
        Thread.sleep(20000);
        System.out.println("Will try to shutdown now...");
        for(Worker worker: threads) {
            worker.shutdown();
        }
    }
于 2019-05-01T06:40:21.153 回答
-4
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();



}
于 2012-12-09T11:31:12.510 回答