订购线程按照创建/启动的顺序运行

我如何按照实例化的顺序订购线程。如何让下面的程序按顺序打印数字1 … 10。

public class ThreadOrdering { public static void main(String[] args) { class MyRunnable implements Runnable{ private final int threadnumber; MyRunnable(int threadnumber){ this.threadnumber = threadnumber; } public void run() { System.out.println(threadnumber); } } for(int i=1; i<=10; i++){ new Thread(new MyRunnable(i)).start(); } } } 

听起来你想要ExecutorService.invokeAll ,它将以固定顺序返回工作线程的结果,即使它们可以按任意顺序排列:

 import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class ThreadOrdering { static int NUM_THREADS = 10; public static void main(String[] args) { ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS); class MyCallable implements Callable { private final int threadnumber; MyCallable(int threadnumber){ this.threadnumber = threadnumber; } public Integer call() { System.out.println("Running thread #" + threadnumber); return threadnumber; } } List> callables = new ArrayList>(); for(int i=1; i<=NUM_THREADS; i++) { callables.add(new MyCallable(i)); } try { List> results = exec.invokeAll(callables); for(Future result: results) { System.out.println("Got result of thread #" + result.get()); } } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } finally { exec.shutdownNow(); } } } 

“我实际上有一些我希望并行执行的部分,然后一旦生成结果,我想以某种顺序合并结果。” 谢谢,这澄清了你的要求。

您可以一次运行它们,但重要的是在线程完成计算时按顺序获取结果。 Thread#join()它们按照你想要获得结果的顺序,或者只是Thread#join()它们全部然后遍历它们以获得它们的结果。

 // Joins the threads back to the main thread in the order we want their results. public class ThreadOrdering { private class MyWorker extends Thread { final int input; int result; MyWorker(final int input) { this.input = input; } @Override public void run() { this.result = input; // Or some other computation. } int getResult() { return result; } } public static void main(String[] args) throws InterruptedException { MyWorker[] workers = new MyWorker[10]; for(int i=1; i<=10; i++) { workers[i] = new MyWorker(i); workers[i].start(); } // Assume it may take a while to do the real computation in the threads. for (MyWorker worker : workers) { // This can throw InterruptedException, but we're just passing that. worker.join(); System.out.println(worker.getResult()); } } } 

简而言之,线程的调度是不确定的。

http://www.janeg.ca/scjp/threads/scheduling.html 死域 – 请勿点击

WaybackMachine版本的上述页面

更长的答案是,如果要执行此操作,则需要手动等待每个线程完成其工作,然后再允许其他线程运行。 请注意,以这种方式,所有线程仍将交错,但在您批准之前,它们将无法完成任何工作。 看看同步保留字。

你可以链接它们 – 也就是说,第一个开始第二个,第二个开始第三个,等等。它们不会真正同时运行,除了每个启动时有点重叠。

 public class ThreadOrdering { public static void main(String[] args) { MyRunnable[] threads = new MyRunnable[10];//index 0 represents thread 1; for(int i=1; i<=10; i++) threads[i] = new MyRunnable(i, threads); new Thread(threads[0].start); } } public class MyRunnable extends Runnable { int threadNumber; MyRunnable[] threads; public MyRunnable(int threadNumber, MyRunnable[] threads) { this.threadnumber = threadnumber; this.threads = threads; } public void run() { System.out.println(threadnumber); if(threadnumber!=10) new Thread(threadnumber).start(); } } 

这是一种方法,没有主线程等待每个结果。 相反,让工作线程共享一个对结果进行排序的对象。

 import java.util.*; public class OrderThreads { public static void main(String... args) { Results results = new Results(); new Thread(new Task(0, "red", results)).start(); new Thread(new Task(1, "orange", results)).start(); new Thread(new Task(2, "yellow", results)).start(); new Thread(new Task(3, "green", results)).start(); new Thread(new Task(4, "blue", results)).start(); new Thread(new Task(5, "indigo", results)).start(); new Thread(new Task(6, "violet", results)).start(); } } class Results { private List results = new ArrayList(); private int i = 0; public synchronized void submit(int order, String result) { while (results.size() <= order) results.add(null); results.set(order, result); while ((i < results.size()) && (results.get(i) != null)) { System.out.println("result delivered: " + i + " " + results.get(i)); ++i; } } } class Task implements Runnable { private final int order; private final String result; private final Results results; public Task(int order, String result, Results results) { this.order = order; this.result = result; this.results = results; } public void run() { try { Thread.sleep(Math.abs(result.hashCode() % 1000)); // simulate a long-running computation } catch (InterruptedException e) {} // you'd want to think about what to do if interrupted System.out.println("task finished: " + order + " " + result); results.submit(order, result); } } 

如果你需要那种细粒度的控件,你不应该使用线程,而是考虑使用一个合适的Executor与Callables或Runnables。 请参阅Executors类以获得广泛的选择。

一个简单的解决方案是使用锁A数组(每个线程一个锁)。 当线程i开始执行时,它获取其关联的锁A[i] 。 当它准备合并其结果时,它释放其锁A[i]并等待锁A[0], A[1], ..., A[i - 1]被释放; 然后它合并结果。

(在此上下文中,线程i表示第i个启动的线程)

我不知道在Java中使用哪些类,但它必须易于实现。 你可以开始阅读这个 。

如果您有更多问题,请随时提出。

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

使用信号量可以非常容易地实现对线程执行顺序的控制。 附带的代码基于Schildt关于Java的书(完整的参考文献……)中提出的想法。 //基于以下提出的想法:// Schildt H。:Java.The.Complete.Reference.9th.Edition。

 import java.util.concurrent.Semaphore; class Manager { int n; // Initially red on semaphores 2&3; green semaphore 1. static Semaphore SemFirst = new Semaphore(1); static Semaphore SemSecond = new Semaphore(0); static Semaphore SemThird = new Semaphore(0); void firstAction () { try { SemFirst.acquire(); } catch(InterruptedException e) { System.out.println("Exception InterruptedException catched"); } System.out.println("First: " ); System.out.println("-----> 111"); SemSecond.release(); } void secondAction() { try{ SemSecond.acquire(); } catch(InterruptedException e) { System.out.println("Exception InterruptedException catched"); } System.out.println("Second: "); System.out.println("-----> 222"); SemThird.release(); } void thirdAction() { try{ SemThird.acquire(); } catch(InterruptedException e) { System.out.println("Exception InterruptedException catched"); } System.out.println("Third: "); System.out.println("-----> 333"); SemFirst.release(); } } class Thread1 implements Runnable { Manager q; Thread1(Manager q) { this.q = q; new Thread(this, "Thread1").start(); } public void run() { q.firstAction(); } } class Thread2 implements Runnable { Manager q; Thread2(Manager q) { this.q = q; new Thread(this, "Thread2").start(); } public void run() { q.secondAction(); } } class Thread3 implements Runnable { Manager q; Thread3(Manager q) { this.q = q; new Thread(this, "Thread3").start(); } public void run() { q.thirdAction(); } } class ThreadOrder { public static void main(String args[]) { Manager q = new Manager(); new Thread3(q); new Thread2(q); new Thread1(q); } } 

这可以在不使用synchronized关键字volatile关键字的帮助下完成。 以下是代码。

 package threadOrderingVolatile; public class Solution { static volatile int counter = 0; static int print = 1; static char c = 'A'; public static void main(String[] args) { // TODO Auto-generated method stub Thread[] ths = new Thread[4]; for (int i = 0; i < ths.length; i++) { ths[i] = new Thread(new MyRunnable(i, ths.length)); ths[i].start(); } } static class MyRunnable implements Runnable { final int thID; final int total; public MyRunnable(int id, int total) { thID = id; this.total = total; } @Override public void run() { while(true) { if (thID == (counter%total)) { System.out.println("thread " + thID + " prints " + c); if(c=='Z'){ c='A'; }else{ c=(char)((int)c+1); } System.out.println("thread " + thID + " prints " + print++); counter++; } else { try { Thread.sleep(30); } catch (InterruptedException e) { // log it } } } } } } 

以下是github链接,它有一个自述文件,详细解释了它是如何发生的。 https://github.com/sankar4git/volatile_thread_ordering