Java 使用生产者和消费者异步访问ConcurrentLinkedQueue

Java 使用生产者和消费者异步访问ConcurrentLinkedQueue,java,multithreading,asynchronous,concurrency,io,Java,Multithreading,Asynchronous,Concurrency,Io,通过调整日志级别和睡眠持续时间,可以近似实现同步。但是,我正在尝试实现对Deque的异步访问,以填充消费者的stringFromProducer字段,同时还处理套接字的输出 这个输出几乎就是我想要的: thufir@dur:~/NetBeansProjects/MudSocketClient$ thufir@dur:~/NetBeansProjects/MudSocketClient$ thufir@dur:~/NetBeansProjects/MudSocketClient$ java -

通过调整日志级别和睡眠持续时间,可以近似实现同步。但是,我正在尝试实现对
Deque
的异步访问,以填充
消费者的
stringFromProducer
字段,同时还处理套接字的输出

这个输出几乎就是我想要的:

thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ java -jar dist/MudSocketClient.jar 
-Dec 13, 2013 11:33:39 PM mudsocketclient.Consumer run
INFO: first
-Dec 13, 2013 11:33:39 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
-Dec 13, 2013 11:33:41 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
a
Dec 13, 2013 11:33:42 PM mudsocketclient.Producer run
INFO: a
-Dec 13, 2013 11:33:43 PM mudsocketclient.Consumer run
INFO: a
-Dec 13, 2013 11:33:43 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
-Dec 13, 2013 11:33:45 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
b
Dec 13, 2013 11:33:46 PM mudsocketclient.Producer run
INFO: b
-Dec 13, 2013 11:33:47 PM mudsocketclient.Consumer run
INFO: b
-Dec 13, 2013 11:33:47 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
-Dec 13, 2013 11:33:49 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
c
Dec 13, 2013 11:33:50 PM mudsocketclient.Producer run
INFO: c
-Dec 13, 2013 11:33:51 PM mudsocketclient.Consumer run
INFO: c
-Dec 13, 2013 11:33:51 PM mudsocketclient.Consumer run
INFO: java.util.NoSuchElementException
^Cthufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
当输入a、b和c时,
生产者和
消费者都会回显它们。但是,在此设置下,
消费者
的套接字连接没有输出

可怜的男人的telnet驱动程序:

public final class Telnet {

    private static Logger log = Logger.getLogger(Telnet.class.getName());

    public Telnet() throws InterruptedException, UnknownHostException, IOException {
        startThreads();
    }

    public static void main(String[] args) throws InterruptedException, UnknownHostException, IOException {
        new Telnet();
    }

    public void startThreads() throws InterruptedException, UnknownHostException, IOException {
        final String host = "rainmaker.wunderground.com";
        final int port = 3000;
        Deque<String> queue = new ConcurrentLinkedDeque<>();
        queue.add("first");
        Thread producer = new Thread(new Producer(queue));
        Thread consumer = new Thread(new Consumer(queue));
        producer.start();
        consumer.start();
    }
}
套接字连接可能有问题<代码>生产者
可能以某种方式阻止或干扰消费者
,因此套接字连接的远程输出无法通过系统打印出来。out
调用:

public class Consumer implements Runnable {

    private static Logger log = Logger.getLogger(Consumer.class.getName());
    final String host = "rainmaker.wunderground.com";
    final int port = 3000;
    private final Socket socket;
    private final InputStream inputStream;
    private final OutputStream outputStream;
    private final Deque<String> queue;
    private String stringFromProducer = "line scan of user input";

    public Consumer(Deque<String> queue) throws UnknownHostException, IOException {
        this.queue = queue;
        socket = new Socket(host, port);
        inputStream = socket.getInputStream();
        outputStream = socket.getOutputStream();
    }

    @Override
    public void run() {
        while (true) {
            try {
                System.out.print((char) inputStream.read());
            } catch (IOException ex) {
                log.fine(ex.toString());
            }
            try {
                stringFromProducer = queue.pop();
                log.info(stringFromProducer);
            } catch (NoSuchElementException ex) {
                log.info(ex.toString());  //spammy output
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    log.fine(e.toString());
                }
            }
        }
    }
}
这实际上是正确的输出,尽管是v e r y s l w l y

保持相同的日志级别,但将睡眠时间减少到1毫秒,可提供:

thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ java -jar dist/MudSocketClient.jar 
-Dec 13, 2013 11:52:42 PM mudsocketclient.Consumer run
INFO: first
-----------------------------------------------------------------------------
*               Welcome to THE WEATHER UNDERGROUND telnet service!            *
------------------------------------------------------------------------------
*                                                                            *
*   National Weather Service information provided by Alden Electronics, Inc. *
*    and updated each minute as reports come in over our data feed.          *
*                                                                            *
*   **Note: If you cannot get past this opening screen, you must use a       *
*   different version of the "telnet" program--some of the ones for IBM      *
*   compatible PC's have a bug that prevents proper connection.              *
*                                                                            *
*           comments: jmasters@wunderground.com                              *
------------------------------------------------------------------------------

Press Return to continue:a
Dec 13, 2013 11:52:45 PM mudsocketclient.Producer run
INFO: a
b
Dec 13, 2013 11:52:47 PM mudsocketclient.Producer run
INFO: b
c
Dec 13, 2013 11:52:48 PM mudsocketclient.Producer run
INFO: c
^Cthufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
现在,通过
System.out
打印套接字连接输出。但是,即使
stringFromProducer
的日志级别为
INFO
,现在也没有来自
Consumer.stringFromProducer
的输出

如何从
Producer
获取输出、用户输入的回显、加上
stringFromProducer
的用户输入的回显以及远程连接输出?通过调整睡眠时间和记录水平,我最多只能管理三分之二的睡眠时间

生产者
消费者
旨在异步运行


我认为减慢执行速度接近于同步,而同步不是我的目标。

我不明白您在这里试图用记录器做什么。为什么不使用正常的System.out stream?哦,只是因为有时候我希望它可以在控制台上清晰地打印出来,有时候则不然。有些输出非常垃圾。我认为消费者中的while循环有点可疑。而且,通常如果您让线程通过并发数据结构进行通信,您可能希望使用阻塞FIFO(比如管道?)。你为什么选择后进先出。这对我来说没有意义。FIFO是正确的,我会改变它,谢谢。然而,我并不想阻止任何事情,我希望双方都能继续运行。@Thufir-他们还有别的事要做吗?mwhs是正确的——正如帖子所说,阻止它并消除产生延迟的睡眠呼叫。
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ java -jar dist/MudSocketClient.jar 
-Dec 13, 2013 11:50:15 PM mudsocketclient.Consumer run
INFO: first
--a
Dec 13, 2013 11:50:18 PM mudsocketclient.Producer run
INFO: a
-Dec 13, 2013 11:50:19 PM mudsocketclient.Consumer run
INFO: a
---b-
Dec 13, 2013 11:50:25 PM mudsocketclient.Producer run
INFO: b
^C
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$ java -jar dist/MudSocketClient.jar 
-Dec 13, 2013 11:52:42 PM mudsocketclient.Consumer run
INFO: first
-----------------------------------------------------------------------------
*               Welcome to THE WEATHER UNDERGROUND telnet service!            *
------------------------------------------------------------------------------
*                                                                            *
*   National Weather Service information provided by Alden Electronics, Inc. *
*    and updated each minute as reports come in over our data feed.          *
*                                                                            *
*   **Note: If you cannot get past this opening screen, you must use a       *
*   different version of the "telnet" program--some of the ones for IBM      *
*   compatible PC's have a bug that prevents proper connection.              *
*                                                                            *
*           comments: jmasters@wunderground.com                              *
------------------------------------------------------------------------------

Press Return to continue:a
Dec 13, 2013 11:52:45 PM mudsocketclient.Producer run
INFO: a
b
Dec 13, 2013 11:52:47 PM mudsocketclient.Producer run
INFO: b
c
Dec 13, 2013 11:52:48 PM mudsocketclient.Producer run
INFO: c
^Cthufir@dur:~/NetBeansProjects/MudSocketClient$ 
thufir@dur:~/NetBeansProjects/MudSocketClient$