Тема Новичок: присоединение потока друг к другу с одновременным - PullRequest
0 голосов
/ 28 декабря 2018

Я хотел бы запустить поток один за другим.Есть ли альтернативный способ марафона с Java 8?Без использования ExecuterService:

public class Marathon {

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

        Runnable task = () -> {
            for (int i = 0; i < 10; i++) {

                System.out.println(Thread.currentThread().getName()+ " is running... " + i);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                }
            }
        };

        Thread t1 = new Thread(task, "Mary");
        Thread t2 = new Thread(task, "David");
        t1.start();
        t1.join(100);
        t2.start();
    }
}

Вывод:

Mary is running... 0 
David is running... 0 
Mary is running... 1 
David is running... 1 
...

Следующий код не работает как марафон:

public class Marathon2 {

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

        ExecutorService service = null;

        Runnable task = () -> {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()
                            + " is running... " + i);
                }
                TimeUnit.MILLISECONDS.sleep(100);

            } catch (InterruptedException e) {
            }
        };
        try {
            service = Executors.newFixedThreadPool(4);

            Future<?> job1 = service.submit(task);
            job1.get(500, TimeUnit.MILLISECONDS);
            Future<?> job2 = service.submit(task);
        } finally {
            if (service != null)
                service.shutdown();
        }
    }
}

Вывод:

pool-1-thread-1 работает ... 0

...

pool-1-thread-1 isработает ... 9

пул-1-нить-2 работает ... 0

...

пул-1-нить-2 выполняется ... 9

Можно ли это сделать с помощью ExecuterService?

Ожидается:

pool-1-thread-1 is running... 0
pool-1-thread-2 is running... 0
...
pool-1-thread-1 is running... 9
pool-1-thread-2 is running... 9

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Два класса не делают одно и то же.Вы, вероятно, можете найти решение самостоятельно, сравнив их.Во-первых, вы точно знаете, как работает ваш первый класс (марафон)?В частности, что, по вашему мнению, делает следующая строка?

t1.join(100);

Поток t1, который только что начал работать, только что вошел в цикл, который считает один раз каждые 200 миллисекунд.Вызов join (100) просто заставляет текущий (основной) поток ждать 100 миллисекунд.Вы добьетесь точно таких же результатов, заменив эту строку на следующую:

Thread.sleep (100);

Теперь, когда основной поток спал в течение 100 миллисекунд, он запускает поток t2.Теперь два потока работают параллельно, и каждые 200 миллисекунд оба потока выводят строку, второй поток задерживается на 100 миллисекунд, чтобы они выглядели равномерно с чередованием.

Теперь давайте рассмотрим ваш второй метод, Marathon2.Несколько отличий от первого класса сразу очевидны:

  1. Сон в Runnable вне цикла, а не внутри.
  2. Сон вRunnable составляет всего 100 миллисекунд вместо 200.
  3. Максимальное время ожидания в главном потоке составляет 500 миллисекунд вместо 100.
  4. Метод Future.get вызывает исключение TimeoutException вместо просто продолжения.В любом случае мы можем просто заменить этот вызов на сон, поскольку это все, что делает первый класс.

Итак, сгладив различия, мы получаем следующий класс Marathon2, который ведет себя аналогичнодругой класс (марафон), с чередованием потоков:

public class Marathon2 {

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

        ExecutorService service = null;

        Runnable task = () -> {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()
                            + " is running... " + i);
                    TimeUnit.MILLISECONDS.sleep(200);
                }

            } catch (InterruptedException e) {
            }
        };
        try {
            service = Executors.newFixedThreadPool(4);

            Future<?> job1 = service.submit(task);
            TimeUnit.MILLISECONDS.sleep(100);
            Future<?> job2 = service.submit(task);
        } finally {
            if (service != null)
                service.shutdown();
        }
    }
}
0 голосов
/ 28 декабря 2018

Не имея дело ни с какими потоками, ни с Исполнителями напрямую, вы можете сделать это с CompletableFuture

 Runnable runnable = () -> System.out.println("hi");
 Runnable runnable1 = () -> System.out.println("there");
 CompletableFuture<Void> all = CompletableFuture.runAsync(runnable).thenRun(runnable1);

 all.whenComplete((x,th) -> {
        System.out.println("both done");
 });

Обратите внимание, что для этого будет использоваться общий пул ForkJoin, но вы все равно можете предоставить свой собственный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...