Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java多线程,让线程并行工作_Java_Multithreading - Fatal编程技术网

Java多线程,让线程并行工作

Java多线程,让线程并行工作,java,multithreading,Java,Multithreading,假设您需要处理两个线程,一个读取器和一个处理器 读取器将读取流数据的一部分,并将其传递给处理器,处理器将执行某些操作 这样做的目的是不要用太多的数据给读者造成压力 在设置中,我 // Processor will pick up data from pipeIn and will place the output in pipeOut Thread p = new Thread(new Processor(pipeIn, pipeOut)); p.start(); // Reader will

假设您需要处理两个线程,一个
读取器
和一个
处理器

读取器
将读取流数据的一部分,并将其传递给
处理器
,处理器将执行某些操作

这样做的目的是不要用太多的数据给读者造成压力

在设置中,我

// Processor will pick up data from pipeIn and will place the output in pipeOut
Thread p = new Thread(new Processor(pipeIn, pipeOut));
p.start();

// Reader will pick a bunch of bits from the InputStream and place it to pipeIn
Thread r = new Thread(new Reader(inputStream, pipeIn));
r.start();
不用说,初始化时,两个管道都不是null

我在想。。。当
处理器
启动后,它会在以下循环中尝试从管道读入:

    while (readingShouldContinue) {
        Thread.sleep(1); // To avoid tight loop

        byte[] justRead = readFrom.getDataCurrentlyInQueue();
        writeDataToPipe(processData(justRead));
    }
如果没有数据要写,它将什么也不写,应该没有问题

读取器
激活并从流中拾取一些数据:

    while ((in.read(buffer)) != -1) {
        // Writes to what processor considers a pipeIn
        writeTo.addDataToQueue(buffer); 
    }
在管道本身中,我同步对数据的访问

public byte[] getDataCurrentlyInQueue() {

    synchronized (q) {
        byte[] a = q.peek();
        q.clear();
        return a;
    }
}
我希望这两个线程半并行运行,在
读取器
处理器
之间交换活动。然而发生的是

  • 读卡器读取前面的所有块
  • 处理器将所有内容视为一个块
请问我错过了什么?

请问我错过了什么

(首先,我应该指出,您遗漏了代码中的一些关键部分以及基于事实的特定答案所需的其他信息。)

我可以想出一些可能的解释:

  • 您的应用程序中可能存在一个bug。猜测这个bug可能是什么并不重要,但是如果您向我们展示更多的代码

  • OS线程调度程序将倾向于让活动线程保持运行,直到它阻塞为止。如果处理器只有一个内核(或者操作系统只允许应用程序使用一个内核),那么第二个线程可能会耗尽。。。足够长的时间让第一个完成

  • 即使您有多个内核,OS线程调度程序分配额外内核的速度也可能很慢,特别是当第二个线程启动后立即阻塞时

  • 缓冲中可能存在某种“粒度”效应,导致工作不出现在队列中。(您可以将其视为一个bug…或一个调优问题。)

  • 这可能只是因为您没有为应用程序提供足够的负载,无法启动多线程


最后,我也搞不懂
线程.sleep
之类的东西。正确编写的多线程应用程序不使用
Thread.sleep
处理长期延迟以外的任何事情;e、 g.在后台执行定期内部管理任务的线程。如果使用
sleep
而不是阻塞,则1)可能会使应用程序无响应,2)可能会鼓励OS线程调度程序为线程提供更少的时间片。这很可能是线程不足问题的根源。

读者在第一次阅读之前阅读了所有内容。这意味着在处理器有机会运行之前,读取已经完成

尝试增加正在读取的字节数,或者以某种方式降低读取器的速度;也许每隔一段时间打一次sleep()电话

顺便说一句,不要投票。这是对CPU周期的可怕浪费,而且根本无法扩展。
还可以使用同步队列,忘记手动锁定

您重新发明了java并发库的一些部分。如果您使用
BlockingQueue
来建模线程,而不是自己同步,那么事情会变得容易得多


基本上,您的生产者会将块放入
阻塞队列
,而您的消费者会(true)在队列上循环并调用get()。这样,生产者将阻塞/等待队列中出现新的块。

使用多个线程时,需要确定是否需要

  • 具有能够高效并行执行的工作
  • 不会增加比您可能实现的改进更多的开销
  • 操作系统或某些库尚未优化,无法执行您尝试执行的操作
在您的例子中,有一个很好的例子说明了何时不使用多线程。操作系统已经被调整为在您请求数据之前预先读取和缓冲数据。读者所做的工作相对来说是微不足道的。创建新缓冲区、将它们添加到队列以及在线程之间传递数据的开销可能大于并行执行的工作量

当您尝试使用多个线程来完成一项任务时,您将得到奇怪的评测/调优结果


+一个好问题。

InputStream.read(字节[])是一个阻塞call@guido你好,圭多。您可以推荐我做些什么吗?试着看看java.nio SocketChannel和ByteBuffer类:AH和Pipe类;)@杰姆:(没有回答)这是什么“线程。睡眠(1);//避免紧循环”?您是否关心所谓的忙循环/忙等待?您应该简单地使用BlockingQueue并调用其take方法。此外,您不需要在队列上同步自己。使用更高级别的并发工具。在这种情况下,阻塞队列就是您所追求的。