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方法。此外,您不需要在队列上同步自己。使用更高级别的并发工具。在这种情况下,阻塞队列就是您所追求的。