按顺序运行Java线程

时间:2011-03-28 15:44:19

标签: java multithreading concurrency java.util.concurrent

你将如何顺序执行三个线程?例如。 Thread1,Thread2,Thread3。无法将一个Thread的引用传递给另一个并从run()方法调用。

所以代码应该是这样的:

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

和out put应该是

 Printing Thread1
 Printing Thread2
 Printing Thread3

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

13 个答案:

答案 0 :(得分:15)

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

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

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

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

答案 1 :(得分: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

正如所料。

答案 2 :(得分:10)

在java.util.concurrent包中使用ExecutorService。更准确地说是使用Executors.newSingleThreadExecutor();

答案 3 :(得分:4)

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

他们想知道你是否可以自己实现线程间通信。但是他们不希望你这么简单(可用的线程参考)。否则,你可以thread.join()

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

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

答案 4 :(得分:4)

如果它与调用这些线程的各种方式无关,理论上,它们应该使用acquire a common sempahore,并在完成打印时释放它。
JDK有一个inbuilt semaphore

答案 5 :(得分:4)

可以使用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();
                }
            }
        }
    };
}

答案 6 :(得分:2)

强制线程以有序的方式运行就像杀死它的概念一样  多线程,它更像是单线程程序&#39;子程序执行。作为面试问题所以一切都好。以下是测试逻辑的程序,不是4个而是50个线程 -

ix

答案 7 :(得分:1)

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

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

P.S。请记住,即使你通过面试,你仍然需要工作! :)

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

答案 8 :(得分:1)

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

我使用过基本的线程通信模型,它也可以更简化。让我们说你有3个线程,一个是打印0,第二个是打印奇数,第三个是打印偶数liker这个 01 02 03 04 05 ....

UPDATE
    TEmployees
SET
    monHourlyRate =  monHourlyRate + 2
WHERE
    dteHireDate > 365

答案 11 :(得分: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();
        }
    }

答案 12 :(得分:-2)

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



}