Заказ потоков для запуска в том порядке, в котором они были созданы/запущены

Как я могу упорядочить потоки в том порядке, в котором они были созданы. как я могу сделать нижеприведенную программу печатать цифры 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();
        }
    }
}

Ответ 1

Похоже, вы хотите 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<Integer> {
            private final int threadnumber;

            MyCallable(int threadnumber){
                this.threadnumber = threadnumber;
            }

            public Integer call() {
                System.out.println("Running thread #" + threadnumber);
                return threadnumber;
            }
        }

        List<Callable<Integer>> callables =
            new ArrayList<Callable<Integer>>();
        for(int i=1; i<=NUM_THREADS; i++) {
            callables.add(new MyCallable(i));
        }
        try {
            List<Future<Integer>> results =
                exec.invokeAll(callables);
            for(Future<Integer> result: results) {
                System.out.println("Got result of thread #" + result.get());
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } catch (ExecutionException ex) {
            ex.printStackTrace();
        } finally {
            exec.shutdownNow();
        }
    }

}

Ответ 2

"На самом деле у меня есть некоторые части, которые я хочу выполнить параллельно, а затем, как только результаты будут сгенерированы, я хочу объединить результаты в определенном порядке". Спасибо, это уточняет, что вы просите.

Вы можете запускать их все сразу, но важно, чтобы их результаты были упорядочены, когда потоки завершат их вычисления. Либо 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());
        }
    }
}

Ответ 3

Проще говоря, планирование потоков является неопределенным.

http://www.janeg.ca/scjp/threads/scheduling.html Мертвый домен - не нажимайте

версия WaybackMachine на предыдущей странице

Более длинный ответ заключается в том, что если вы хотите это сделать, вам нужно будет вручную дождаться завершения каждого потока, прежде чем вы разрешите другому. Обратите внимание, что таким образом все потоки все равно будут чередоваться, но они не будут выполнять какую-либо работу, пока вы не дадите добро. Посмотрите на синхронизированное зарезервированное слово.

Ответ 4

Вы можете связать их, то есть сначала запустить второй, второй запустить третий и т.д. Они не будут работать одновременно, за исключением небольшого перекрытия при каждом запуске.

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

Ответ 5

Вот способ сделать это, не имея главного потока, который ждет каждого результата. Вместо этого, рабочие потоки совместно используют объект, который заказывает результаты.

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<String> results = new ArrayList<String>();
    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);
    }
}

Ответ 6

Если вам нужен этот мелкозернистый элемент управления, вы не должны использовать потоки, а вместо этого смотрите на использование подходящего Executor с Callables или Runnables. См. Класс "Исполнители" для широкого выбора.

Ответ 7

Простым решением было бы использовать массив A блокировок (по одной блокировке на поток). Когда поток i начинает выполнение, он получает связанный с ним замок A[i]. Когда он готов к объединению своих результатов, он освобождает свою блокировку A[i] и ждет блокировки A[0], A[1], ..., A[i - 1] для освобождения; затем он объединяет результаты.

(В этом контексте поток i означает i -й запущенный поток)

Я не знаю, какие классы использовать в Java, но это должно быть легко реализовать. Вы можете начать читать this.

Если у вас есть еще вопросы, не стесняйтесь спрашивать.

Ответ 8

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

Ответ 9

Управление порядком выполнения потоков может быть легко реализовано с помощью семафоров. Приведенный код основан на идеях, представленных в книге Шильдта на 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);
    }
}