注意:我有这个目标,我对此有很多疑问,但是我借此机会全部实现了这些目标,因为我不知道是否应该建议使用相同的代码/问题。
我有一个生产者(RunnableProducer
),该生产者具有多个称为RunnableWorker
的消费者。 RunnableWorker
可能有多个相同类别的使用者。最后,其信息被简单的使用者RunnableConsumer
占用。
信息的大小可以改变,可以增加或减少(称为resampling
),然后可以通过过滤器进行修改(放大或衰减)。这些操作由RunnableWorker
执行。
我试图在Runnable
接口之间执行交互建模。
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
public class TestPipedRunnable {
public static void main(String... args) {
int numBytes = 8;
RunnableProducer runnableProducer = new RunnableProducer("runnableProducer", numBytes);
RunnableWorker runnableWorkerStage0Unique = new RunnableWorker("runnableWorkerStage0Unique", numBytes, runnableProducer.getPipedInputStream());
RunnableWorker runnableWorkerStage1Number1 = new RunnableWorker("runnableWorkerStage1Number1", numBytes);
RunnableWorker runnableWorkerStage1Number2 = new RunnableWorker("runnableWorkerStage1Number2", numBytes);
runnableWorkerStage0Unique.addPipedOutputStream(runnableWorkerStage1Number1.getPipedOutputStream());
runnableWorkerStage0Unique.addPipedOutputStream(runnableWorkerStage1Number2.getPipedOutputStream());
RunnableConsumer runnableConsumer1 = new RunnableConsumer("runnableConsumer1", numBytes);
runnableWorkerStage1Number1.addPipedOutputStream(runnableConsumer1.getPipedOutputStream());
RunnableConsumer runnableConsumer2 = new RunnableConsumer("runnableConsumer2", numBytes);
runnableWorkerStage1Number2.addPipedOutputStream(runnableConsumer2.getPipedOutputStream());
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(runnableProducer);
executorService.execute(runnableWorkerStage0Unique);
executorService.execute(runnableWorkerStage1Number1);
executorService.execute(runnableWorkerStage1Number2);
executorService.execute(runnableConsumer1);
executorService.execute(runnableConsumer2);
executorService.shutdown();
}
public static String getRandomString(int size) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; i++) {
char c = (char) (new Random().nextInt(25) + 'a');
sb.append(c);
}
return sb.toString();
}
public static class RunnableProducer implements Runnable {
private PipedInputStream pipedInputStream;
private PipedOutputStream pipedOutputStream;
private String name;
private final int bufferSize;
public RunnableProducer(String name, int bufferSize) {
this.name = name;
this.bufferSize = bufferSize;
pipedInputStream = new PipedInputStream();
pipedOutputStream = new PipedOutputStream();
try {
pipedOutputStream.connect(pipedInputStream);
} catch (IOException e) {
System.out.println("Exception:" + e.getMessage());
}
}
public RunnableProducer(String name, int bufferSize, PipedOutputStream pipedOutputStream) {
this.name = name;
this.bufferSize = bufferSize;
this.pipedOutputStream = pipedOutputStream;
}
@Override
public void run() {
while (true) {
try {
// byte[] outBytesSamples = new byte[bufferSize];
// new Random().nextBytes(outBytesSamples);
byte[] outBytesSamples = getRandomString(bufferSize).getBytes();
pipedOutputStream.write(outBytesSamples);
pipedOutputStream.flush();
System.out.println(name + ".Produced " + new String(outBytesSamples));
int timeSleeping = ThreadLocalRandom.current().nextInt(500, 1000);
Thread.sleep(timeSleeping);
} catch (Exception e) {
System.out.println("Exception with " + name);
System.out.println("Exception:" + e.getMessage());
}
}
}
public PipedInputStream getPipedInputStream() {
return pipedInputStream;
}
}
public static class RunnableConsumer implements Runnable {
private PipedInputStream pipedInputStream;
private PipedOutputStream pipedOutputStream;
private String name;
private final int bufferSize;
public RunnableConsumer(String name, int bufferSize) {
this.name = name;
this.bufferSize = bufferSize;
pipedInputStream = new PipedInputStream();
pipedOutputStream = new PipedOutputStream();
try {
pipedInputStream.connect(pipedOutputStream);
} catch (IOException e) {
System.out.println("Exception:" + e.getMessage());
}
}
public RunnableConsumer(String name, int bufferSize, PipedInputStream pipedInputStream) {
this.name = name;
this.bufferSize = bufferSize;
this.pipedInputStream = pipedInputStream;
}
@Override
public void run() {
while (true) {
try {
byte[] inBytesSamples = new byte[bufferSize];
pipedInputStream.read(inBytesSamples);
System.out.println(name + ".Consume " + new String(inBytesSamples));
int timeSleeping = ThreadLocalRandom.current().nextInt(500, 1000);
Thread.sleep(timeSleeping);
} catch (Exception e) {
System.out.println("Exception with " + name);
System.out.println("Exception:" + e.getMessage());
}
}
}
public PipedOutputStream getPipedOutputStream() {
return pipedOutputStream;
}
}
public static class RunnableWorker implements Runnable {
private String name;
private final int bufferSize;
private PipedInputStream pipedInputStream;
private PipedOutputStream pipedOutputStream;
private final List<PipedOutputStream> listPipedOutputStream;
public RunnableWorker(String name, int bufferSize, PipedInputStream pipedInputStream) {
this.name = name;
this.bufferSize = bufferSize;
this.pipedInputStream = pipedInputStream;
this.listPipedOutputStream = new ArrayList<>();
}
public RunnableWorker(String name, int bufferSize, PipedOutputStream pipedOutputStream) {
this.name = name;
this.bufferSize = bufferSize;
this.pipedOutputStream = pipedOutputStream;
this.listPipedOutputStream = new ArrayList<>();
}
public RunnableWorker(String name, int bufferSize) {
this.name = name;
this.bufferSize = bufferSize;
this.pipedInputStream = new PipedInputStream();
try {
this.pipedOutputStream = new PipedOutputStream(pipedInputStream);
} catch (IOException e) {
System.out.println("Exception with " + name);
System.out.println("Exception:" + e.getMessage());
}
this.listPipedOutputStream = new ArrayList<>();
}
@Override
public void run() {
int qtyBytes;
byte[] incomingBytes = new byte[bufferSize * 2];
if (pipedInputStream != null) {
try {
while ((qtyBytes = pipedInputStream.read(incomingBytes)) != -1) {
byte[] inBytesSamples = new byte[qtyBytes];
System.arraycopy(incomingBytes, 0, inBytesSamples, 0, qtyBytes);
// Begin Simulate Change of Size and Change information
// applying FFT and others complex and heavy process
//
double change = 0.0;//ThreadLocalRandom.current().nextDouble(-0.5, 0.5);
int newSize = (int) (qtyBytes * (1.0 + change));
byte[] outBytesSamples = new byte[newSize];
int minSize = newSize < qtyBytes ? newSize : qtyBytes;
System.arraycopy(inBytesSamples, 0, outBytesSamples, 0, minSize);
if (newSize > qtyBytes) {
byte[] restBytesSamples = getRandomString(newSize - qtyBytes).getBytes();//
//byte[] restBytesSamples = new byte[newSize - qtyBytes];
//new Random().nextBytes(restBytesSamples);
System.arraycopy(restBytesSamples, 0, outBytesSamples, minSize, restBytesSamples.length);
}
//new Random().nextBytes(outBytesSamples);
// Finish Simulate Change of Size and Change information
writepipedOutputStream(outBytesSamples);
//writepipedOutputStream(inBytesSamples); // For Test Porpouse (not changes applied to information)
}
} catch (IOException e) {
System.out.println("Exception with " + name);
System.out.println("Exception:" + e.getMessage());
}
}
}
public PipedInputStream getPipedInputStream() {
return pipedInputStream;
}
public PipedOutputStream getPipedOutputStream() {
return pipedOutputStream;
}
public void addPipedOutputStream(PipedOutputStream pipedOutputStream) {
listPipedOutputStream.add(pipedOutputStream);
}
public void delPipedOutputStream(PipedOutputStream pipedOutputStream) {
listPipedOutputStream.remove(pipedOutputStream);
}
private void writepipedOutputStream(byte[] buffer) {
listPipedOutputStream.forEach(pipedOutputStream -> {
try {
pipedOutputStream.write(buffer);
} catch (IOException e) {
System.out.println("Exception with " + name);
System.out.println("Exception:" + e.getMessage());
}
});
}
}
}
当我在RunnableWorker
行中使用 writepipedOutputStream(inBytesSamples); // For Test Porpouse (not changes applied to information)
行时,我得到了输出(似乎一切正常)。
--- exec-maven-plugin:1.5.0:exec (default-cli) @ MPMC ---
runnableProducer.Produced nbtsavuf
runnableProducer.Produced pwrnttbi
runnableConsumer1.Consume nbtsavuf
runnableConsumer2.Consume nbtsavuf
runnableProducer.Produced rsuaffdo
runnableConsumer1.Consume pwrnttbi
runnableConsumer2.Consume pwrnttbi
runnableProducer.Produced clmldcfx
runnableConsumer1.Consume rsuaffdo
runnableConsumer2.Consume rsuaffdo
runnableProducer.Produced tnkosyrv
但是,当我在RunnableWorker
行的 writepipedOutputStream(outBytesSamples);
--- exec-maven-plugin:1.5.0:exec (default-cli) @ MPMC ---
runnableProducer.Produced bniqphsw
runnableProducer.Produced vfjmwqai
Exception with runnableConsumer2
Exception with runnableConsumer1
java.io.StreamCorruptedException: invalid stream header: 77087666
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:862)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:354)
at org.joseluisbz.mpmc.TestPipedRunnable$RunnableConsumer.run(TestPipedRunnable.java:142)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.io.StreamCorruptedException: invalid stream header: 77087666
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:862)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:354)
at org.joseluisbz.mpmc.TestPipedRunnable$RunnableConsumer.run(TestPipedRunnable.java:142)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.io.StreamCorruptedException: invalid stream header: 6A6D7771
Exception with runnableConsumer2
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:862)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:354)
at org.joseluisbz.mpmc.TestPipedRunnable$RunnableConsumer.run(TestPipedRunnable.java:142)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Exception with runnableConsumer1 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
有些时候我得到了
java.io.StreamCorruptedException: invalid type code: C4
问题
是否可以将我的建模转换为使用BlockingQueue? BlockingQueue vs PipedOutputStream and PipedInputStream
可以做哪些改进来避免出现异常情况?(考虑到工人在将信息传递给自己的消费者之前将花费很长时间进行指示的更改)。
针对这个提出的问题是否会有发展模式?