Java "разговор" между двумя потоками: потоковые потоки ввода / вывода - PullRequest
1 голос
/ 16 марта 2011

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

Я не мог заставить его работать, либо с Java.nio.Pipe и java.io.PipedInputStream / java.io.PipedOutput.Stream

Вот пример кода того, что я хочу сделать:

Основной класс, настраивающий все.

public static void main(String[] args) {
        // TODO
        // Create two communication channel, and bind them together

        MyThread t1 = new MyThread(channel1Reader, channel2Writer, 0);
        MyThread t2 = new MyThread(channel2Reader, channel1Writer, 1);

        t1.run();
        t2.run();

    }

Класс темы:

public class MyThread extends Thread {
    private ? inputStream;
    private ? outputStream;
    private boolean canTalk;
    private int id;

    public MyThread(? inputStream, ? outputStream, boolean isStarting, int id) {
        this.inputStream = inputStream;
        this.outputStream = outputStream;
        this.canTalk = isStarting;
        this.id = id;
    }

    public void run() {
        while(true) {
            if(canTalk) {
                String s = getRandomWord();
                // TODO
                // Write s to the output stream
            }

            // TODO
            // Wait until receiving a String on the input stream
            String s2 = the word I just received
            Log.info("Thread " + id + " received the word '" + s2 + "'");
            canTalk = true;
            Thread.sleep(1000);
        }
    }

Есть идеи?

Спасибо!

Ответы [ 3 ]

1 голос
/ 16 марта 2011

Вы используете здесь

    t1.run();
    t2.run();

При этом выполняются методы запуска обоих потоковых объектов в текущем потоке, и один за другим. Созданные потоки фактически не запускаются.

Таким образом, коммуникация не может работать, поскольку поток чтения еще не запущен, когда пишет поток записи, и наоборот. Пользователь

    t1.start();
    t2.start();

здесь или используйте ThreadPool с объектами Runnable вместо подклассов Thread.

1 голос
/ 16 марта 2011

PipedInout / OutputStream полезны, если у вас есть библиотека, которая должна принимать поток ввода / вывода.В противном случае это один из наименее дружественных способов обмена данными между потоками.

Однако самый простой способ обмена данными между потоками - это использование ExecutorService.Вы можете отправлять задачи Callable в службу и получать результаты из Future

. Другой подход заключается в использовании нескольких BlockingQueue , но это не сильно экономит и не обеспечивает функциональность, которую предоставляет ExecutorService.

Проблема с вашим примером состоит в том, что намного проще реализовать в виде одного потока.Я предлагаю вам взглянуть на функциональность, которая лучше всего выполняется несколькими потоками.

0 голосов
/ 16 марта 2011

Я обычно использую Queue, вероятно, подкрепленный LinkedList.

Читать:

synchronized (q) {
    while (q.isEmpty() && !stopSignal) {
        q.wait(3000);
    }
    return q.poll();
}

Написать:

synchronized (q) {
    q.add(item);
    q.notify();
}
...