Получение вывода потока

Если метод equals() присутствует в классе java.lang.Object, и ожидается, что он проверяет эквивалентность состояния объектов! Это означает, что содержимое объектов. В то время как ожидается, что оператор == проверяет, что фактические экземпляры объекта одинаковы или нет.

Пример

Рассмотрим две различные ссылочные переменные, str1 и str2:

str1 = new String("abc");
str2 = new String("abc");

Если вы используете equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

, вы получите выход как TRUE, если вы используете ==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

Теперь вы получите вывод FALSE в качестве вывода, потому что оба str1 и str2 указывают на два разных объекта, хотя оба они имеют одинаковое строковое содержимое. Именно из-за new String() каждый новый объект создается каждый раз.

11
задан Community 23 May 2017 в 10:29
поделиться

7 ответов

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

Можно использовать ExecutorService, такой как ThreadPoolExecutor к отправьте () Callables. Это возвратит будущий объект.

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

Те конструкции значительно упростят наиболее распространенные потоковые операции.

Я хотел бы разъясниться о блокировании get():

Идея состоит в том, что Вы хотите выполнить некоторые задачи ( Callables) это делает некоторую работу (вычисление, доступ ресурса...), где Вам не нужен результат прямо сейчас. Можно просто зависеть от Executor выполнять Ваш код каждый раз, когда это хочет (если это - a ThreadPoolExecutor затем это будет работать каждый раз, когда свободный Поток доступен). Затем в какой-то момент вовремя Вам, вероятно, нужен результат вычисления для продолжения. В этой точке Вы, как предполагается, звоните get(). Если задача уже работала в той точке, то get() просто сразу возвратит значение. Если задача не завершалась, то get() вызов будет ожидать, пока задача не выполнена. Это обычно желаемо, так как Вы не можете продолжить без результата задач так или иначе.

Когда Вы не нуждаетесь в значении для продолжения, но хотели бы знать об этом, если это уже доступно (возможно для показа чего-то в UI), затем можно легко звонить isDone() и только звоните get() если это возвращается true).

25
ответ дан 3 December 2019 в 02:21
поделиться

Ваш сценарий все еще немного неясен.

При выполнении пакетного задания можно хотеть использовать invokeAll. Это заблокирует Ваш основной поток, пока все задачи не будут завершены. Нет никакого "активного ожидания" с этим подходом, где основной поток потратил бы впустую ЦП, опрашивающий isDone метод будущего. В то время как этот метод возвращает список Futures, они уже "сделаны". (Существует также перегруженная версия, которая может тайм-аут перед завершением, которое могло бы быть более безопасно использовать с некоторыми задачами.) Это может быть намного более чисто, чем попытка собрать набор Future объекты самостоятельно и пытающийся проверить их состояние или заблокировать их get методы индивидуально.

Если это - интерактивное приложение с задачами, эпизодически отделенными, чтобы быть выполненным в фоновом режиме, использование обратного вызова, как предложено nick.holt является большим подходом. Здесь, Вы используете submit a Runnable. run метод вызывает обратный вызов с результатом, когда он был вычислен. С этим подходом можно отбросить Future возвращенный submit, если Вы не хотите смочь к cancel выполняющиеся задачи, не закрывая целое ExecutorService.

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

1
ответ дан 3 December 2019 в 02:21
поделиться

Вы могли создать интерфейс lister, что основные реализации программы, который называет рабочий, после того как он закончил выполняться, это - работа.

Тем путем Вы не должны опрашивать вообще.

Вот интерфейс в качестве примера:

/**
 * Listener interface to implement to be called when work has
 * finished.
 */
public interface WorkerListener {
    public void workDone(WorkerThread thread);
}

Вот пример фактического потока, который делает некоторую работу и уведомляет, что это - слушатели:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Thread to perform work
 */
public class WorkerThread implements Runnable {
    private List listeners = new ArrayList();
    private List results;

    public void run() {
        // Do some long running work here

        try {
            // Sleep to simulate long running task
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        results = new ArrayList();
        results.add("Result 1");

        // Work done, notify listeners
        notifyListeners();
    }

    private void notifyListeners() {
        for (Iterator iter = listeners.iterator(); iter.hasNext();) {
            WorkerListener listener = (WorkerListener) iter.next();
            listener.workDone(this);
        }
    }

    public void registerWorkerListener(WorkerListener listener) {
        listeners.add(listener);
    }

    public List getResults() {
        return results;
    }
}

И наконец, основная программа, которая запускает рабочий поток и регистрирует слушателя, чтобы быть уведомленной однажды работа, сделана:

import java.util.Iterator;
import java.util.List;

/**
 * Class to simulate a main program
 */
public class MainProg {
    public MainProg() {
        WorkerThread worker = new WorkerThread();
        // Register anonymous listener class
        worker.registerWorkerListener(new WorkerListener() {
            public void workDone(WorkerThread thread) {
                System.out.println("Work done");
                List results = thread.getResults();
                for (Iterator iter = results.iterator(); iter.hasNext();) {
                    String result = (String) iter.next();
                    System.out.println(result);
                }
            }
        });

        // Start the worker thread
        Thread thread = new Thread(worker);
        thread.start();

        System.out.println("Main program started");
    }

    public static void main(String[] args) {
        MainProg prog = new MainProg();
    }
}
4
ответ дан 3 December 2019 в 02:21
поделиться

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

Мой Java груб, но Вы хотите что-то как следующее:

Если один поток должен ожидать вывода другого потока, необходимо использовать условную переменную.

final Lock lock = new ReentrantLock();
final Condition cv = lock.newCondition();

Поток, заинтересованный выводом другой угрозы, должен звонить cv.wait(). Это заставит текущий поток блокироваться. Когда рабочий поток закончен, работая, он должен звонить cv.signal(). Это заставит заблокированный поток становиться разблокированным, позволяя этому осмотреть вывод рабочего потока.

1
ответ дан 3 December 2019 в 02:21
поделиться

Как альтернатива параллелизму API, как описано Saua (и если основной поток не должен знать, когда рабочий поток заканчивается) Вы могли использовать публиковать/подписывать шаблон.

В этом сценарии ребенок Thread/Runnable дан слушателя, который знает, как обработать результат и который призван обратно к когда ребенок Thread/Runnable завершается.

1
ответ дан 3 December 2019 в 02:21
поделиться

Поток подкласса, и дает Вашему классу метод, который возвращает результат. Когда метод называют, если результат не был создан, еще, то соединение () с Потоком. Когда соединение () возвраты, работа Вашего Потока будет сделана, и результат должен быть доступным; возвратите его.

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

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

1
ответ дан 3 December 2019 в 02:21
поделиться

Как отмечено saua: используйте конструкции, предлагаемые java.util.concurrent. Если Вы застреваете с пред 1,5 (или 5.0), JRE, Вы, мог бы обратиться к виду прокрутки Вашего собственного, но Вы еще лучше из при помощи бэкпорта: http://backport-jsr166.sourceforge.net/

0
ответ дан 3 December 2019 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: