Java 8 多延迟使用者、并发句柄、阻塞队列
注意:我确实尝试过简化这段代码 我有多个进程(不同类型)由多个Runnable执行 我试图用图表来简化这种情况 我有一个Java 8 多延迟使用者、并发句柄、阻塞队列,java-8,runnable,producer-consumer,blockingqueue,reentrantreadwritelock,Java 8,Runnable,Producer Consumer,Blockingqueue,Reentrantreadwritelock,注意:我确实尝试过简化这段代码 我有多个进程(不同类型)由多个Runnable执行 我试图用图表来简化这种情况 我有一个RunnableProducer在它的时间内进行生产,生产出来的产品被转移到一个RunnableWorker,它执行一些操作处理程序Down(蓝色箭头)执行一个过程,并将它分发给它的接收者(同类)。 如果标记了RunnableWorker(code而不是null),则它必须执行一种特殊类型的进程Processor,并将其返回给转移它的“父”RunnableWorker。 也就
RunnableProducer
在它的时间内进行生产,生产出来的产品被转移到一个RunnableWorker
,它执行一些操作处理程序Down
(蓝色箭头)执行一个过程,并将它分发给它的接收者(同类)。
如果标记了RunnableWorker
(code
而不是null),则它必须执行一种特殊类型的进程Processor
,并将其返回给转移它的“父”RunnableWorker
。
也就是说,您的接收器收集了许多正在执行另一个附加处理器up
(绿色箭头)的数据,请注意绿色箭头的数量。
初始的RunnableWorker
将所有数据(在同一类中介的帮助下)传输到RunnableConsumer
,而不将它们混合,后者将执行另一项任务(对于此问题,print
)
RunnableProducer
只应在RunnableConsumer
最终可以接收/收集生成的所有内容时生成(由RunnableWorker的
传输)。
RunnableProducer
可以单独关闭。
但是,RunnableConsumer
必须在RunnableConsumer
生产时运行,直到他消费了所有东西(及其变体)
注意:您可以复制、粘贴、编译和运行
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TestCollectorRunnable1 {
public static void main(String... args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Counter counter = new Counter();
LifeCycle rcLifeCycle = new LifeCycle();
LifeCycle rpLifeCycle = new LifeCycle();
RunnableConsumer rc = new RunnableConsumer("rc", rcLifeCycle, rpLifeCycle, executorService, counter);
RunnableProducer rp = new RunnableProducer("rp", rpLifeCycle, rcLifeCycle, executorService, counter);
RunnableWorker rw0 = new RunnableWorker("rw0", executorService, counter, null, null, rp.getOutBlockingQueue(), rc.getInBlockingQueue());
RunnableWorker rw11 = new RunnableWorker("rw11", executorService, counter, null, rw0);
RunnableWorker rw12 = new RunnableWorker("rw12", executorService, counter, null, rw0);
rw0.addBlockingQueue(rw11.getInputBlockingQueue());
rw0.addBlockingQueue(rw12.getInputBlockingQueue());
RunnableWorker rw211 = new RunnableWorker("rw211", executorService, counter, 1, rw11);
RunnableWorker rw212 = new RunnableWorker("rw212", executorService, counter, 2, rw11);
RunnableWorker rw213 = new RunnableWorker("rw213", executorService, counter, 3, rw11);
rw11.addBlockingQueue(rw211.getInputBlockingQueue());
rw11.addBlockingQueue(rw212.getInputBlockingQueue());
rw11.addBlockingQueue(rw213.getInputBlockingQueue());
RunnableWorker rw221 = new RunnableWorker("rw221", executorService, counter, 4, rw12);
RunnableWorker rw222 = new RunnableWorker("rw222", executorService, counter, 5, rw12);
rw12.addBlockingQueue(rw221.getInputBlockingQueue());
rw12.addBlockingQueue(rw222.getInputBlockingQueue());
//Simulate Turn off
new Timer().schedule(new TimerTask() {
@Override
public void run() {
rp.stop();
}
}, ThreadLocalRandom.current().nextLong(100L, 1000L));
}
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 final String name;
private final LifeCycle ownLifeCycle;
private final LifeCycle outLifeCycle;
private final ExecutorService executorService;
private final Counter counter;
private final int bufferSize;
private final BlockingQueue<ChunkDTO> outBlockingQueue;
private volatile boolean isRunning = false;
public RunnableProducer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, ExecutorService executorService, Counter counter) {
this(name, ownLifeCycle, outLifeCycle, executorService, counter, new SynchronousQueue/*LinkedBlockingQueue*/<>());
}
public RunnableProducer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, ExecutorService executorService, Counter counter, BlockingQueue<ChunkDTO> outBlockingQueue) {
this.name = name;
this.ownLifeCycle = ownLifeCycle;
this.outLifeCycle = outLifeCycle;
this.executorService = executorService;
this.counter = counter;
this.bufferSize = 8;
this.outBlockingQueue = outBlockingQueue;
this.ownLifeCycle.setCreated(true);
this.executorService.execute(this);
}
@Override
public void run() {
long quantity = 0;
isRunning = true;
//Blocking Wait (not very elegant)
/*
block until the consumer can consume without losing what is produced and processed
*/
while (!outLifeCycle.isRunning()) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
while (/*isRunning*/quantity < 5) {
ownLifeCycle.setRunning(true);
try {
byte[] outBytesSamples = getRandomString(bufferSize).getBytes();
ChunkDTO chunkDTO = new ChunkDTO(outBytesSamples, quantity, null);
outBlockingQueue.put(chunkDTO);
System.out.println(name + ".Produced " + new String(outBytesSamples) + "\t index:" + quantity);
int timeSleeping = ThreadLocalRandom.current().nextInt(10, 100);
Thread.sleep(timeSleeping);
} catch (Exception e) {
}
quantity++;
counter.setValue(quantity);
}
System.out.println(name + "\tSent:" + quantity);
}
public BlockingQueue<ChunkDTO> getOutBlockingQueue() {
return outBlockingQueue;
}
public void stop() {
isRunning = false;
}
}
public static class RunnableConsumer implements Runnable {
private final String name;
private final LifeCycle ownLifeCycle;
private final LifeCycle outLifeCycle;
private final ExecutorService executorService;
private final Counter counter;
private final BlockingQueue<ChunkDTO> inBlockingQueue;
public RunnableConsumer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, ExecutorService executorService, Counter counter) {
this(name, ownLifeCycle, outLifeCycle, executorService, counter, new SynchronousQueue/*LinkedBlockingQueue*/<>());
}
public RunnableConsumer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, ExecutorService executorService, Counter counter, BlockingQueue<ChunkDTO> inBlockingQueue) {
this.name = name;
this.ownLifeCycle = ownLifeCycle;
this.outLifeCycle = outLifeCycle;
this.executorService = executorService;
this.counter = counter;
this.inBlockingQueue = inBlockingQueue;
this.ownLifeCycle.setCreated(true);
this.executorService.execute(this);
}
@Override
public void run() {
if (inBlockingQueue != null) {
try {
int quantity = 0;
while (!outLifeCycle.isCreated() || outLifeCycle.isRunning()/*haya recolectado lo que tiene que recolectar*/) {
ownLifeCycle.setRunning(true);
ChunkDTO chunkDTO = inBlockingQueue.take();
System.out.println(name + ".Collected " + new String(chunkDTO.getChunk()) + "\t index:" + chunkDTO.getIndex() + "\t pitch:" + chunkDTO.getPitch());
quantity++;
}
System.out.println(name + "\tReceived:" + quantity);
} catch (InterruptedException e) {
}
}
}
public BlockingQueue<ChunkDTO> getInBlockingQueue() {
return inBlockingQueue;
}
}
public static class RunnableWorker {
private final ExecutorService executorService;
private final RunnableWorker parent;
private final BlockingQueue<ChunkDTO> inputBlockingQueue;
private final BlockingQueue<ChunkDTO> outputBlockingQueue;
private final List<BlockingQueue<ChunkDTO>> downList;
private final List<BlockingQueue<ChunkDTO>> upList;
private final Set<Integer> codes;
public RunnableWorker(String name, ExecutorService executorService, Counter counter, Integer code, RunnableWorker parent, BlockingQueue<ChunkDTO> inputBlockingQueue, BlockingQueue<ChunkDTO> outputBlockingQueue) {
this.executorService = executorService;
this.parent = parent;
this.inputBlockingQueue = inputBlockingQueue;
this.outputBlockingQueue = outputBlockingQueue;
this.downList = new ArrayList<>();
this.upList = new ArrayList<>(Arrays.asList(new SynchronousQueue/*LinkedBlockingQueue*/<>()));
this.codes = new HashSet<>();
//RUNNABLE DISTRIBUTOR
this.executorService.execute(() -> {
if (inputBlockingQueue != null) {
try {
while (true) {
ChunkDTO chunkDTO = inputBlockingQueue.take();
/*
if (codes.size() > 0) {
System.out.println(name + " codes.length:" + codes.size());
}
if (parent == null) {
System.out.println(name + ".Worked " + new String(chunkDTO.getChunk()) + "\tindex:" + chunkDTO.getIndex());
}
// */
if (code == null) {
new ProcessorDown(executorService, chunkDTO, downList);
} else {
ChunkDTO returned = new ChunkDTO(chunkDTO.getChunk(), chunkDTO.getIndex(), code);
System.out.println("\t\t" + name + ".Returned " + returned.toString());
if (parent != null) {
new Processor(executorService, returned, parent.getUpList());
parent.addCodeSon(code);
}
}
}
} catch (Exception e) {
}
}
});
//RUNNABLE COLLECTOR
if (code == null) {
this.executorService.execute(() -> {
int quantity = 0;
while (quantity == 0) {
BlockingQueue<ChunkDTO> outBlockingQueue = upList.get(0);
if (outBlockingQueue != null) {
try {
while (quantity == 0 || (quantity > 0 && quantity < codes.size() * (counter.getValue()))) {
ChunkDTO chunkDTO = outBlockingQueue.take();
/*
System.out.println("\t" + name + ".quantity: " + quantity + ", codes.size():" + codes.size() + ", counter.getValue():" + counter.getValue() + ", total:" + (codes.size() * counter.getValue())
+ "\r\t\tcchunk:" + chunkDTO
+ "\r\t\tcodes:" + codes.stream().map(i -> i.toString()).collect(Collectors.joining(",")));
// */
if (chunkDTO != null) {
if (parent == null) {
outputBlockingQueue.put(chunkDTO);
System.out.println("\t\t" + name + ".Collected " + chunkDTO.toString());
} else {
new ProcessorUp(executorService, chunkDTO, parent.getUpList());
}
quantity++;
}
}
/*
if (quantity != 0) {
String codesString = codes.stream().map(i -> i.toString()).collect(Collectors.joining(","));
System.out.println("\t" + name + "\tWorked:" + quantity + ", \tcodes:" + codesString);
}
// */
} catch (InterruptedException e) {
}
}
}
});
}
}
public void addCodeSon(Integer code) {
if (parent != null) {
parent.addCodeSon(code);
}
codes.add(code);
}
public RunnableWorker(String name, ExecutorService executorService, Counter counter, Integer code, RunnableWorker parent) {
this(name, executorService, counter, code, parent, new SynchronousQueue/*LinkedBlockingQueue*/<>(), new SynchronousQueue/*LinkedBlockingQueue*/<>());
}
public BlockingQueue<ChunkDTO> getInputBlockingQueue() {
return inputBlockingQueue;
}
public void addBlockingQueue(BlockingQueue<ChunkDTO> blockingQueue) {
downList.add(blockingQueue);
}
public void delBlockingQueue(BlockingQueue<ChunkDTO> blockingQueue) {
downList.remove(blockingQueue);
}
public List<BlockingQueue<ChunkDTO>> getUpList() {
return upList;
}
}
public static class Processor implements Runnable {
private final ExecutorService executorService;
private final List<BlockingQueue<ChunkDTO>> listOutput;
private final ChunkDTO inChunkDTO;
public Processor(ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
this.executorService = executorService;
this.listOutput = listOutput;
this.inChunkDTO = inChunkDTO;
this.executorService.execute(this);
}
@Override
public void run() {
if (inChunkDTO != null) {
try {
byte[] outBytes = internalProcessing(inChunkDTO.getChunk());
ChunkDTO outChunkDTO = new ChunkDTO(outBytes, inChunkDTO.getIndex(), inChunkDTO.getPitch());
if (listOutput != null) {
listOutput.forEach(output -> {
try {
output.put(outChunkDTO);
} catch (Exception e) {
}
});
}
} catch (Exception e) {
}
}
}
}
public static class ProcessorDown extends Processor {
public ProcessorDown(ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
super(executorService, inChunkDTO, listOutput);
}
}
public static class ProcessorUp extends Processor {
public ProcessorUp(ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
super(executorService, inChunkDTO, listOutput);
}
}
private static byte[] internalProcessing(byte[] in) {
byte[] out = in;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
return out;
}
public static class ChunkDTO {
private final byte[] chunk;
private final long index;
private final Integer pitch;
public ChunkDTO(byte[] chunk, long index, Integer pitch) {
this.chunk = chunk;
this.index = index;
this.pitch = pitch;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
public Integer getPitch() {
return pitch;
}
@Override
public String toString() {
return "ChunkDTO{" + "chunk=" + new String(chunk) + ", index=" + index + ", pitch=" + pitch + '}';
}
}
public static class Counter {
private final ReadWriteLock rwLock;
private Long value;
public Counter() {
this.rwLock = new ReentrantReadWriteLock();
this.value = 0L;
}
public Long getValue() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return value;
} finally {
readLock.unlock();
}
}
public void setValue(Long value) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.value = value;
} finally {
writeLock.unlock();
}
}
}
public static class LifeCycle {
private final ReadWriteLock rwLock;
private boolean created;
private boolean running;
private boolean finished;
public LifeCycle() {
this.rwLock = new ReentrantReadWriteLock();
}
public boolean isCreated() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return created;
} finally {
readLock.unlock();
}
}
public void setCreated(boolean created) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.created = created;
} finally {
writeLock.unlock();
}
}
public boolean isRunning() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return running;
} finally {
readLock.unlock();
}
}
public void setRunning(boolean running) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.running = running;
} finally {
writeLock.unlock();
}
}
public boolean isFinished() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return finished;
} finally {
readLock.unlock();
}
}
public void setFinished(boolean finished) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.finished = finished;
} finally {
writeLock.unlock();
}
}
}
}
如您所见,制作人发送了5个区块,但我损失了大部分,我需要接收25个(对于本例)。消费者只收集了很少的物品我的逻辑有什么问题?
我不知道创建两个runnable是否是RunnableWorker类的好解决方案是否有更好的实施方案?
我认识到我有一个可怕的方法阻止生产者等待消费者你推荐什么解决方案?我自己的答案
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TestCollectorRunnable7a {
public static void main(String... args) {
List<Future<?>> futureList = new ArrayList<>();
ExecutorService executorService = Executors.newCachedThreadPool();
Counter counter = new Counter();
CodesList codesList = new CodesList();
LifeCycle rcLifeCycle = new LifeCycle();
LifeCycle rpLifeCycle = new LifeCycle();
RunnableConsumer rc = new RunnableConsumer("rc", rcLifeCycle, rpLifeCycle, futureList, executorService, counter, codesList);
RunnableProducer rp = new RunnableProducer("rp", rpLifeCycle, rcLifeCycle, futureList, executorService, counter);
RunnableWorker rw0 = new RunnableWorker("rw0", rcLifeCycle, futureList, executorService, counter, codesList, null, null, rp.getOutBlockingQueue(), rc.getInBlockingQueue());
RunnableWorker rw11 = new RunnableWorker("rw11", rcLifeCycle, futureList, executorService, counter, codesList, null, rw0);
RunnableWorker rw12 = new RunnableWorker("rw12", rcLifeCycle, futureList, executorService, counter, codesList, null, rw0);
rw0.addBlockingQueue(rw11.getInputBlockingQueue());
rw0.addBlockingQueue(rw12.getInputBlockingQueue());
RunnableWorker rw211 = new RunnableWorker("rw211", rcLifeCycle, futureList, executorService, counter, codesList, 1, rw11);
RunnableWorker rw212 = new RunnableWorker("rw212", rcLifeCycle, futureList, executorService, counter, codesList, 2, rw11);
RunnableWorker rw213 = new RunnableWorker("rw213", rcLifeCycle, futureList, executorService, counter, codesList, 3, rw11);
rw11.addBlockingQueue(rw211.getInputBlockingQueue());
rw11.addBlockingQueue(rw212.getInputBlockingQueue());
rw11.addBlockingQueue(rw213.getInputBlockingQueue());
RunnableWorker rw221 = new RunnableWorker("rw221", rcLifeCycle, futureList, executorService, counter, codesList, 4, rw12);
RunnableWorker rw222 = new RunnableWorker("rw222", rcLifeCycle, futureList, executorService, counter, codesList, 5, rw12);
rw12.addBlockingQueue(rw221.getInputBlockingQueue());
rw12.addBlockingQueue(rw222.getInputBlockingQueue());
//Simulate Turn off
new Timer(false).schedule(new TimerTask() {
@Override
public void run() {
rp.stop();
}
}, ThreadLocalRandom.current().nextLong(100L, 1000L));
}
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 final String name;
private final LifeCycle ownLifeCycle;
private final LifeCycle outLifeCycle;
private final List<Future<?>> futureList;
private final ExecutorService executorService;
private final Counter counter;
private final int bufferSize;
private final BlockingQueue<ChunkDTO> outBlockingQueue;
private volatile boolean isRunning = false;
public RunnableProducer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter) {
this(name, ownLifeCycle, outLifeCycle, futureList, executorService, counter, new LinkedBlockingQueue<>());
}
public RunnableProducer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter, BlockingQueue<ChunkDTO> outBlockingQueue) {
this.name = name;
this.ownLifeCycle = ownLifeCycle;
this.outLifeCycle = outLifeCycle;
this.futureList = futureList;
this.executorService = executorService;
this.counter = counter;
this.bufferSize = 8;
this.outBlockingQueue = outBlockingQueue;
this.ownLifeCycle.setCreated(true);
this.futureList.add(this.executorService.submit(this));
}
@Override
public void run() {
long quantity = 0;
while (!outLifeCycle.isRunning()) {
try {
Thread.sleep(100);
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
isRunning = true;
ownLifeCycle.setRunning(true);
while (isRunning) {
try {
byte[] outBytesSamples = getRandomString(bufferSize).getBytes();
ChunkDTO chunkDTO = new ChunkDTO(outBytesSamples, quantity, null);
outBlockingQueue.put(chunkDTO);
System.out.println(name + ".Produced " + new String(outBytesSamples) + "\t index:" + quantity);
int timeSleeping = ThreadLocalRandom.current().nextInt(10, 100);
Thread.sleep(timeSleeping);
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
quantity++;
counter.setValue(quantity);
}
ownLifeCycle.setRunning(false);
System.out.println(name + "\tSent:" + quantity);
ownLifeCycle.setFinished(true);
}
public BlockingQueue<ChunkDTO> getOutBlockingQueue() {
return outBlockingQueue;
}
public void stop() {
isRunning = false;
}
}
public static class RunnableConsumer implements Runnable {
private final String name;
private final LifeCycle ownLifeCycle;
private final LifeCycle outLifeCycle;
private final List<Future<?>> futureList;
private final ExecutorService executorService;
private final Counter counter;
private final Counter intCounter;
private final CodesList codesList;
private final BlockingQueue<ChunkDTO> inBlockingQueue;
public RunnableConsumer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter, CodesList codesList) {
this(name, ownLifeCycle, outLifeCycle, futureList, executorService, counter, new LinkedBlockingQueue/*SynchronousQueue LinkedBlockingQueue*/<>(), codesList);
}
public RunnableConsumer(String name, LifeCycle ownLifeCycle, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter, BlockingQueue<ChunkDTO> inBlockingQueue, CodesList codesList) {
this.name = name;
this.ownLifeCycle = ownLifeCycle;
this.outLifeCycle = outLifeCycle;
this.futureList = futureList;
this.executorService = executorService;
this.counter = counter;
this.inBlockingQueue = inBlockingQueue;
this.intCounter = new Counter();
this.codesList = codesList;
this.ownLifeCycle.setCreated(true);
this.futureList.add(this.executorService.submit(() -> {
while (!this.outLifeCycle.isFinished() || intCounter.getValue() < counter.getValue() * codesList.size()) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
inBlockingQueue.add(new ChunkStopper(null, -1, null));
}));
this.futureList.add(this.executorService.submit(this));
}
@Override
public void run() {
if (inBlockingQueue != null) {
try {
long quantity = 0;
ownLifeCycle.setRunning(true);
while (true) {
ChunkDTO chunkDTO = inBlockingQueue.take();
if (chunkDTO instanceof ChunkStopper) {
ownLifeCycle.setRunning(false);
break;
}
System.out.println(name + ".Consumed " + new String(chunkDTO.getChunk()) + "\t index:" + chunkDTO.getIndex() + "\t code:" + chunkDTO.getPitch() + ", \tquantity:" + quantity);
quantity++;
intCounter.setValue(quantity);
}
ownLifeCycle.setRunning(false);
System.out.println(name + "\tReceived:" + quantity);
ownLifeCycle.setFinished(true);
} catch (InterruptedException ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public BlockingQueue<ChunkDTO> getInBlockingQueue() {
return inBlockingQueue;
}
}
public static class RunnableWorker {
private final LifeCycle ownLifeCycle;
private final LifeCycle outLifeCycle;
private final List<Future<?>> futureList;
private final ExecutorService executorService;
private final Counter intCounter;
private final CodesList codesList;
private final RunnableWorker parent;
private final BlockingQueue<ChunkDTO> inputBlockingQueue;
private final BlockingQueue<ChunkDTO> outputBlockingQueue;
private final List<BlockingQueue<ChunkDTO>> downList;
private final List<BlockingQueue<ChunkDTO>> upList;
private final Set<Integer> codes;
public RunnableWorker(String name, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter, CodesList codesList, Integer code, RunnableWorker parent, BlockingQueue<ChunkDTO> inputBlockingQueue, BlockingQueue<ChunkDTO> outputBlockingQueue) {
this.ownLifeCycle = new LifeCycle();
this.outLifeCycle = outLifeCycle;
this.futureList = futureList;
this.executorService = executorService;
this.intCounter = new Counter();
this.codesList = codesList;
this.parent = parent;
this.inputBlockingQueue = inputBlockingQueue;
this.outputBlockingQueue = outputBlockingQueue;
this.downList = new ArrayList<>();
this.upList = new ArrayList<>(Arrays.asList(new LinkedBlockingQueue<>()));
this.codes = new HashSet<>();
if (code != null) {
this.codesList.addCode(code);
}
this.futureList.add(this.executorService.submit(() -> {
while (!outLifeCycle.isFinished()) {
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
//System.out.println(name + " -> Consumer Finished!");
while (true) {
try {
BlockingQueue<ChunkDTO> outBlockingQueue = upList.get(0);
outBlockingQueue.add(new ChunkStopper(null, -1, null));
break;
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
while (true) {
try {
inputBlockingQueue.add(new ChunkStopper(null, -1, null));
break;
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
}));
//RUNNABLE DISTRIBUTOR
this.futureList.add(this.executorService.submit(() -> {
long quantity = 0;
if (inputBlockingQueue != null) {
try {
ownLifeCycle.setRunning(true);
while (true) {
ChunkDTO chunkDTO = inputBlockingQueue.take();
if (chunkDTO instanceof ChunkStopper) {
break;
}
if (code == null) {
new ProcessorDown(futureList, executorService, chunkDTO, downList);
} else {
ChunkDTO returned = new ChunkDTO(chunkDTO.getChunk(), chunkDTO.getIndex(), code);
//System.out.println("\t\t" + name + ".Returned " + returned.toString());
if (parent != null) {
new Processor(this.futureList, executorService, returned, parent.getUpList());
parent.addCodeSon(code);
}
}
quantity++;
intCounter.setValue(quantity);
}
ownLifeCycle.setRunning(false);
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
//System.out.println(name + ". DISTRIBUTOR Finished");
}));
//RUNNABLE COLLECTOR
if (code == null) {
this.futureList.add(this.executorService.submit(() -> {
int quantity = 0;
while (quantity == 0) {
BlockingQueue<ChunkDTO> outBlockingQueue = upList.get(0);
if (outBlockingQueue != null) {
try {
while (true) {
ChunkDTO chunkDTO = outBlockingQueue.take();
if (chunkDTO instanceof ChunkStopper) {
break;
}
if (parent == null) {
outputBlockingQueue.put(chunkDTO);
//System.out.println("\t\t" + name + ".Collected " + chunkDTO.toString());
} else {
new ProcessorUp(futureList, executorService, chunkDTO, parent.getUpList());
}
quantity++;
}
} catch (InterruptedException ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//System.out.println(name + ". COLLECTOR Finished");
}));
}
}
public LifeCycle getOwnLifeCycle() {
return ownLifeCycle;
}
public void addCodeSon(Integer code) {
if (parent != null) {
parent.addCodeSon(code);
}
codes.add(code);
}
public RunnableWorker(String name, LifeCycle outLifeCycle, List<Future<?>> futureList, ExecutorService executorService, Counter counter, CodesList codesList, Integer code, RunnableWorker parent) {
this(name, outLifeCycle, futureList, executorService, counter, codesList, code, parent, new LinkedBlockingQueue<>(), new LinkedBlockingQueue<>());
}
public BlockingQueue<ChunkDTO> getInputBlockingQueue() {
return inputBlockingQueue;
}
public void addBlockingQueue(BlockingQueue<ChunkDTO> blockingQueue) {
downList.add(blockingQueue);
}
public List<BlockingQueue<ChunkDTO>> getUpList() {
return upList;
}
}
public static class Processor implements Runnable {
private final ExecutorService executorService;
private final List<BlockingQueue<ChunkDTO>> listOutput;
private final ChunkDTO inChunkDTO;
public Processor(List<Future<?>> futureList, ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
this.executorService = executorService;
this.listOutput = listOutput;
this.inChunkDTO = inChunkDTO;
futureList.add(this.executorService.submit(this));
}
@Override
public void run() {
if (inChunkDTO != null) {
try {
byte[] outBytes = internalProcessing(inChunkDTO.getChunk());
ChunkDTO outChunkDTO = new ChunkDTO(outBytes, inChunkDTO.getIndex(), inChunkDTO.getPitch());
if (listOutput != null) {
listOutput.forEach(output -> {
try {
output.put(outChunkDTO);
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
} catch (Exception ex) {
Logger.getLogger(TestCollectorRunnable7a.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public static class ProcessorDown extends Processor {
public ProcessorDown(List<Future<?>> futureList, ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
super(futureList, executorService, inChunkDTO, listOutput);
}
}
public static class ProcessorUp extends Processor {
public ProcessorUp(List<Future<?>> futureList, ExecutorService executorService, ChunkDTO inChunkDTO, List<BlockingQueue<ChunkDTO>> listOutput) {
super(futureList, executorService, inChunkDTO, listOutput);
}
}
private static byte[] internalProcessing(byte[] in) {
byte[] out = in;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
return out;
}
public static class ChunkStopper extends ChunkDTO {
public ChunkStopper(byte[] chunk, long index, Integer pitch) {
super(chunk, index, pitch);
}
}
public static class ChunkDTO {
private final byte[] chunk;
private final long index;
private final Integer pitch;
public ChunkDTO(byte[] chunk, long index, Integer pitch) {
this.chunk = chunk;
this.index = index;
this.pitch = pitch;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
public Integer getPitch() {
return pitch;
}
@Override
public String toString() {
return "ChunkDTO{" + "chunk=" + new String(chunk) + ", index=" + index + ", pitch=" + pitch + '}';
}
}
public static class Counter {
private final ReadWriteLock rwLock;
private Long value;
public Counter() {
this.rwLock = new ReentrantReadWriteLock();
this.value = 0L;
}
public Long getValue() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return value;
} finally {
readLock.unlock();
}
}
public void setValue(Long value) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.value = value;
} finally {
writeLock.unlock();
}
}
}
public static class CodesList {
private final List<Integer> codes;
private final ReadWriteLock rwLock;
public CodesList() {
this.codes = new ArrayList<>();
this.rwLock = new ReentrantReadWriteLock();
}
public void addCode(Integer code) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
codes.add(code);
} finally {
writeLock.unlock();
}
}
public int size() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return codes.size();
} finally {
readLock.unlock();
}
}
}
public static class LifeCycle {
private final ReadWriteLock rwLock;
private boolean created;
private boolean running;
private boolean finished;
public LifeCycle() {
this.rwLock = new ReentrantReadWriteLock();
}
public boolean isCreated() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return created;
} finally {
readLock.unlock();
}
}
public void setCreated(boolean created) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.created = created;
} finally {
writeLock.unlock();
}
}
public boolean isRunning() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return running;
} finally {
readLock.unlock();
}
}
public void setRunning(boolean running) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.running = running;
} finally {
writeLock.unlock();
}
}
public boolean isFinished() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return finished;
} finally {
readLock.unlock();
}
}
public void setFinished(boolean finished) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
this.finished = finished;
} finally {
writeLock.unlock();
}
}
}
}
另一个测试
rp.Produced iufalvxu index:0
rp.Produced ammjynnm index:1
rc.Consumed iufalvxu index:0 code:4, quantity:0
rc.Consumed iufalvxu index:0 code:2, quantity:1
rc.Consumed iufalvxu index:0 code:1, quantity:2
rc.Consumed iufalvxu index:0 code:5, quantity:3
rc.Consumed iufalvxu index:0 code:3, quantity:4
rc.Consumed ammjynnm index:1 code:1, quantity:5
rc.Consumed ammjynnm index:1 code:3, quantity:6
rc.Consumed ammjynnm index:1 code:4, quantity:7
rc.Consumed ammjynnm index:1 code:5, quantity:8
rc.Consumed ammjynnm index:1 code:2, quantity:9
rp.Produced clbecbge index:2
rc.Consumed clbecbge index:2 code:1, quantity:10
rc.Consumed clbecbge index:2 code:4, quantity:11
rc.Consumed clbecbge index:2 code:3, quantity:12
rc.Consumed clbecbge index:2 code:5, quantity:13
rc.Consumed clbecbge index:2 code:2, quantity:14
rp.Produced sletiovo index:3
rc.Consumed sletiovo index:3 code:5, quantity:15
rc.Consumed sletiovo index:3 code:1, quantity:16
rc.Consumed sletiovo index:3 code:2, quantity:17
rc.Consumed sletiovo index:3 code:4, quantity:18
rc.Consumed sletiovo index:3 code:3, quantity:19
rp Sent:4
rc Received:20
我会先让它为一个工作者工作,然后为3个工作者工作(即树深度2):您可能可以用更少的代码发现错误,或者更快地得到答案。总的来说,您的方法感觉不正确,有更简单的方法。还有更好的结构可以在Java中实现相同的结果。选择一个取决于需求。我理解你的观点,但我需要展示不同的行为。级别3的人的行为与级别2的人不同,级别1从一个级别(生产者)接收,然后将收集到的信息传递给另一个级别(消费者)。@AlexPakka我认为我对生命周期的处理非常糟糕。我不确定工人的构造函数中是否应该有两个可运行的,但是,当尝试只处理一个时,并发可能会对我造成不利影响。“阻止生产者等待消费者的可怕方法”-如果有一个队列已经进行了必要的阻止,比如说……a
BlockingQueue
?@Holger hi!,此代码while(!outLifeCycle.isRunning()){try{Thread.sleep(10);}catch(异常e){}
rp.Produced egxjthjr index:0
rp.Produced pdiutqkt index:1
rc.Consumed egxjthjr index:0 code:2, quantity:0
rc.Consumed egxjthjr index:0 code:1, quantity:1
rc.Consumed egxjthjr index:0 code:5, quantity:2
rc.Consumed egxjthjr index:0 code:3, quantity:3
rc.Consumed egxjthjr index:0 code:4, quantity:4
rc.Consumed pdiutqkt index:1 code:4, quantity:5
rp.Produced dwqtvoun index:2
rc.Consumed pdiutqkt index:1 code:2, quantity:6
rc.Consumed pdiutqkt index:1 code:5, quantity:7
rc.Consumed pdiutqkt index:1 code:1, quantity:8
rc.Consumed pdiutqkt index:1 code:3, quantity:9
rp.Produced ydwqheks index:3
rc.Consumed dwqtvoun index:2 code:4, quantity:10
rc.Consumed dwqtvoun index:2 code:5, quantity:11
rc.Consumed dwqtvoun index:2 code:1, quantity:12
rc.Consumed dwqtvoun index:2 code:2, quantity:13
rc.Consumed dwqtvoun index:2 code:3, quantity:14
rc.Consumed ydwqheks index:3 code:1, quantity:15
rc.Consumed ydwqheks index:3 code:3, quantity:16
rc.Consumed ydwqheks index:3 code:2, quantity:17
rc.Consumed ydwqheks index:3 code:5, quantity:18
rc.Consumed ydwqheks index:3 code:4, quantity:19
rp.Produced tamvejvq index:4
rp.Produced tpqjkgqd index:5
rc.Consumed tamvejvq index:4 code:4, quantity:20
rc.Consumed tamvejvq index:4 code:5, quantity:21
rc.Consumed tamvejvq index:4 code:2, quantity:22
rc.Consumed tamvejvq index:4 code:3, quantity:23
rc.Consumed tamvejvq index:4 code:1, quantity:24
rp.Produced quchekol index:6
rc.Consumed tpqjkgqd index:5 code:4, quantity:25
rc.Consumed tpqjkgqd index:5 code:2, quantity:26
rc.Consumed tpqjkgqd index:5 code:5, quantity:27
rc.Consumed tpqjkgqd index:5 code:3, quantity:28
rc.Consumed tpqjkgqd index:5 code:1, quantity:29
rc.Consumed quchekol index:6 code:4, quantity:30
rc.Consumed quchekol index:6 code:1, quantity:31
rc.Consumed quchekol index:6 code:5, quantity:32
rc.Consumed quchekol index:6 code:2, quantity:33
rc.Consumed quchekol index:6 code:3, quantity:34
rp Sent:7
rc Received:35
rp.Produced iufalvxu index:0
rp.Produced ammjynnm index:1
rc.Consumed iufalvxu index:0 code:4, quantity:0
rc.Consumed iufalvxu index:0 code:2, quantity:1
rc.Consumed iufalvxu index:0 code:1, quantity:2
rc.Consumed iufalvxu index:0 code:5, quantity:3
rc.Consumed iufalvxu index:0 code:3, quantity:4
rc.Consumed ammjynnm index:1 code:1, quantity:5
rc.Consumed ammjynnm index:1 code:3, quantity:6
rc.Consumed ammjynnm index:1 code:4, quantity:7
rc.Consumed ammjynnm index:1 code:5, quantity:8
rc.Consumed ammjynnm index:1 code:2, quantity:9
rp.Produced clbecbge index:2
rc.Consumed clbecbge index:2 code:1, quantity:10
rc.Consumed clbecbge index:2 code:4, quantity:11
rc.Consumed clbecbge index:2 code:3, quantity:12
rc.Consumed clbecbge index:2 code:5, quantity:13
rc.Consumed clbecbge index:2 code:2, quantity:14
rp.Produced sletiovo index:3
rc.Consumed sletiovo index:3 code:5, quantity:15
rc.Consumed sletiovo index:3 code:1, quantity:16
rc.Consumed sletiovo index:3 code:2, quantity:17
rc.Consumed sletiovo index:3 code:4, quantity:18
rc.Consumed sletiovo index:3 code:3, quantity:19
rp Sent:4
rc Received:20