how to terminate retrieval from a blocking queue - java

I have some code where i execute a several tasks using Executors and a Blocking Queue. The results have to be returned as an iterator because that is what the application that i work on expects. However, there is a 1:N relationship between the task and the results added to the queue, so i cannot use the ExecutorCompletionService. While calling hasNext(), i need to know when all the tasks have finished and added all the results to the queue, so that i can stop the retrieval of results from the queue. Note, that once items are put on the queue, another thread should be ready to consume (Executor.invokeAll(), blocks until all tasks have completed, which is not what i want, nor a timeout). This was my first attempt, i am using an AtomicInteger just to demonstrate the point even though it will not work. Could someone help me in undestanding how i can solve this issue?
public class ResultExecutor<T> implements Iterable<T> {
private BlockingQueue<T> queue;
private Executor executor;
private AtomicInteger count;
public ResultExecutor(Executor executor) {
this.queue = new LinkedBlockingQueue<T>();
this.executor = executor;
count = new AtomicInteger();
}
public void execute(ExecutorTask task) {
executor.execute(task);
}
public Iterator<T> iterator() {
return new MyIterator();
}
public class MyIterator implements Iterator<T> {
private T current;
public boolean hasNext() {
if (count.get() > 0 && current == null)
{
try {
current = queue.take();
count.decrementAndGet();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return current != null;
}
public T next() {
final T ret = current;
current = null;
return ret;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public class ExecutorTask implements Runnable{
private String name;
public ExecutorTask(String name) {
this.name = name;
}
private int random(int n)
{
return (int) Math.round(n * Math.random());
}
#SuppressWarnings("unchecked")
public void run() {
try {
int random = random(500);
Thread.sleep(random);
queue.put((T) (name + ":" + random + ":1"));
queue.put((T) (name + ":" + random + ":2"));
queue.put((T) (name + ":" + random + ":3"));
queue.put((T) (name + ":" + random + ":4"));
queue.put((T) (name + ":" + random + ":5"));
count.addAndGet(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the calling code looks like:
Executor e = Executors.newFixedThreadPool(2);
ResultExecutor<Result> resultExecutor = new ResultExecutor<Result>(e);
resultExecutor.execute(resultExecutor.new ExecutorTask("A"));
resultExecutor.execute(resultExecutor.new ExecutorTask("B"));
Iterator<Result> iter = resultExecutor.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}

Use "poison" objects in the Queue to signal that a task will provide no more results.
class Client
{
public static void main(String... argv)
throws Exception
{
BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
ExecutorService workers = Executors.newFixedThreadPool(2);
workers.execute(new ExecutorTask("A", queue));
workers.execute(new ExecutorTask("B", queue));
Iterator<String> results =
new QueueMarkersIterator<String>(queue, ExecutorTask.MARKER, 2);
while (results.hasNext())
System.out.println(results.next());
}
}
class QueueMarkersIterator<T>
implements Iterator<T>
{
private final BlockingQueue<? extends T> queue;
private final T marker;
private int count;
private T next;
QueueMarkersIterator(BlockingQueue<? extends T> queue, T marker, int count)
{
this.queue = queue;
this.marker = marker;
this.count = count;
this.next = marker;
}
public boolean hasNext()
{
if (next == marker)
next = nextImpl();
return (next != marker);
}
public T next()
{
if (next == marker)
next = nextImpl();
if (next == marker)
throw new NoSuchElementException();
T tmp = next;
next = marker;
return tmp;
}
/*
* Block until the status is known. Interrupting the current thread
* will cause iteration to cease prematurely, even if elements are
* subsequently queued.
*/
private T nextImpl()
{
while (count > 0) {
T o;
try {
o = queue.take();
}
catch (InterruptedException ex) {
count = 0;
Thread.currentThread().interrupt();
break;
}
if (o == marker) {
--count;
}
else {
return o;
}
}
return marker;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
class ExecutorTask
implements Runnable
{
static final String MARKER = new String();
private static final Random random = new Random();
private final String name;
private final BlockingQueue<String> results;
public ExecutorTask(String name, BlockingQueue<String> results)
{
this.name = name;
this.results = results;
}
public void run()
{
int random = ExecutorTask.random.nextInt(500);
try {
Thread.sleep(random);
}
catch (InterruptedException ignore) {
}
final int COUNT = 5;
for (int idx = 0; idx < COUNT; ++idx)
results.add(name + ':' + random + ':' + (idx + 1));
results.add(MARKER);
}
}

I believe a Future is what you're looking for. It allows you to associate asynchronous tasks with a result object, and query the status of that result. For each task you begin, keep a reference to its Future and use that to determine whether or not it has completed.

If I understand your problem correctly (which I'm not sure I do), you can prevent an infinite wait on an empty queue by using [BlockingQueue.poll][1] instead of take(). This lets you specify a timeout, after which time null will be returned if the queue is empty.
If you drop this straight into your hasNext implementation (with an appropriately short timeout), the logic will be correct. An empty queue will return false while a queue with
entities remaining will return true.
[1]: http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html#poll(long, java.util.concurrent.TimeUnit)

Here is an alternate solution that uses a non-blocking queue with wait/notify, AtomicInteger and a callback.
public class QueueExecutor implements CallbackInterface<String> {
public static final int NO_THREADS = 26;
private Object syncObject = new Object();
private AtomicInteger count;
Queue<String> queue = new LinkedList<String>();
public void execute() {
count = new AtomicInteger(NO_THREADS);
ExecutorService executor = Executors.newFixedThreadPool(NO_THREADS/2);
for(int i=0;i<NO_THREADS;i++)
executor.execute(new ExecutorTask<String>("" + (char) ('A'+i), queue, this));
Iterator<String> iter = new QueueIterator<String>(queue, count);
int count = 0;
while (iter.hasNext()) {
System.out.println(iter.next());
count++;
}
System.out.println("Handled " + count + " items");
}
public void callback(String result) {
System.out.println(result);
count.decrementAndGet();
synchronized (syncObject) {
syncObject.notify();
}
}
public class QueueIterator<T> implements Iterator<T> {
private Queue<T> queue;
private AtomicInteger count;
public QueueIterator(Queue<T> queue, AtomicInteger count) {
this.queue = queue;
this.count = count;
}
public boolean hasNext() {
while(true) {
synchronized (syncObject) {
if(queue.size() > 0)
return true;
if(count.get() == 0)
return false;
try {
syncObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public T next() {
synchronized (syncObject) {
if(hasNext())
return queue.remove();
else
return null;
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
class ExecutorTask<T> implements Runnable {
private String name;
private Queue<T> queue;
private CallbackInterface<T> callback;
public ExecutorTask(String name, Queue<T> queue,
CallbackInterface<T> callback) {
this.name = name;
this.queue = queue;
this.callback = callback;
}
#SuppressWarnings("unchecked")
public void run() {
try {
Thread.sleep(1000);
Random randomX = new Random();
for (int i = 0; i < 5; i++) {
synchronized (syncObject) {
Thread.sleep(randomX.nextInt(10)+1);
queue.add((T) (name + ":" + ":" + i));
syncObject.notify();
}
}
callback.callback((T) (name + ": Done"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public interface CallbackInterface<T> {
void callback(T result);
}
And the calling code is simply:
QueueExecutor exec = new QueueExecutor();
exec.execute();

I am not sure I understand you, but why can't the worker threads put themselves Lists onto the Queue. You can then make a custom iterator that goes over the queue in an outer loop and through the subiterators. All without concurrency magic.

Related

Global combine not producing output Apache Beam

I am trying to write an unbounded ping pipeline that takes output from a ping command and parses it to determine some statistics about the RTT (avg/min/max) and for now, just print the results.
I have already written an unbounded ping source that outputs each line as it comes in. The results are windowed every second for every 5 seconds of pings. The windowed data is fed to a Combine.globally call to statefully process the string outputs. The problem is that the accumulators are never merged and the output is never extracted. This means that the pipeline never continues past this point. What am I doing wrong here?
public class TestPingIPs {
public static void main(String[] args)
{
PipelineOptions options = PipelineOptionsFactory.create();
Pipeline pipeline = Pipeline.create(options);
String destination = "8.8.8.8";
PCollection<PingResult> res =
/*
Run the unbounded ping command. Only the lines where the result of the ping command are returned.
No statistics or first startup lines are returned here.
*/
pipeline.apply("Ping command",
PingCmd.read()
.withPingArguments(PingCmd.PingArguments.create(destination, -1)))
/*
Window the ping command strings into 5 second sliding windows produced every 1 second
*/
.apply("Window strings",
Window.into(SlidingWindows.of(Duration.standardSeconds(5))
.every(Duration.standardSeconds(1))))
/*
Parse and aggregate the strings into a PingResult object using stateful processing.
*/
.apply("Combine the pings",
Combine.globally(new ProcessPings()).withoutDefaults())
/*
Test our output to see what we get here
*/
.apply("Test output",
ParDo.of(new DoFn<PingResult, PingResult>() {
#ProcessElement
public void processElement(ProcessContext c)
{
System.out.println(c.element().getAvgRTT());
System.out.println(c.element().getPacketLoss());
c.output(c.element());
}
}));
pipeline.run().waitUntilFinish();
}
static class ProcessPings extends Combine.CombineFn<String, RttStats, PingResult> {
private long getRTTFromLine(String line){
long rtt = Long.parseLong(line.split("time=")[1].split("ms")[0]);
return rtt;
}
#Override
public RttStats createAccumulator()
{
return new RttStats();
}
#Override
public RttStats addInput(RttStats mutableAccumulator, String input)
{
mutableAccumulator.incTotal();
if (input.contains("unreachable")) {
_unreachableCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("General failure")) {
_transmitFailureCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("timed out")) {
_timeoutCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("could not find")) {
_unknownHostCount.inc();
mutableAccumulator.incPacketLoss();
}
else {
_successfulCount.inc();
mutableAccumulator.add(getRTTFromLine(input));
}
return mutableAccumulator;
}
#Override
public RttStats mergeAccumulators(Iterable<RttStats> accumulators)
{
Iterator<RttStats> iter = accumulators.iterator();
if (!iter.hasNext()){
return createAccumulator();
}
RttStats running = iter.next();
while (iter.hasNext()){
RttStats next = iter.next();
running.addAll(next.getVals());
running.addLostPackets(next.getLostPackets());
}
return running;
}
#Override
public PingResult extractOutput(RttStats stats)
{
stats.calculate();
boolean connected = stats.getPacketLoss() != 1;
return new PingResult(connected, stats.getAvg(), stats.getMin(), stats.getMax(), stats.getPacketLoss());
}
private final Counter _successfulCount = Metrics.counter(ProcessPings.class, "Successful pings");
private final Counter _unknownHostCount = Metrics.counter(ProcessPings.class, "Unknown hosts");
private final Counter _transmitFailureCount = Metrics.counter(ProcessPings.class, "Transmit failures");
private final Counter _timeoutCount = Metrics.counter(ProcessPings.class, "Timeouts");
private final Counter _unreachableCount = Metrics.counter(ProcessPings.class, "Unreachable host");
}
I would guess that there are some issues with the CombineFn that I wrote, but I can't seem to figure out what's going wrong here! I tried following the example here, but there's still something I must be missing.
EDIT: I added the ping command implementation below. This is running on a Direct Runner while I test.
PingCmd.java:
public class PingCmd {
public static Read read(){
if (System.getProperty("os.name").startsWith("Windows")) {
return WindowsPingCmd.read();
}
else{
return null;
}
}
WindowsPingCmd.java:
public class WindowsPingCmd extends PingCmd {
private WindowsPingCmd()
{
}
public static PingCmd.Read read()
{
return new WindowsRead.Builder().build();
}
static class PingCheckpointMark implements UnboundedSource.CheckpointMark, Serializable {
#VisibleForTesting
Instant oldestMessageTimestamp = Instant.now();
#VisibleForTesting
transient List<String> outputs = new ArrayList<>();
public PingCheckpointMark()
{
}
public void add(String message, Instant timestamp)
{
if (timestamp.isBefore(oldestMessageTimestamp)) {
oldestMessageTimestamp = timestamp;
}
outputs.add(message);
}
#Override
public void finalizeCheckpoint()
{
oldestMessageTimestamp = Instant.now();
outputs.clear();
}
// set an empty list to messages when deserialize
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
outputs = new ArrayList<>();
}
#Override
public boolean equals(#Nullable Object other)
{
if (other instanceof PingCheckpointMark) {
PingCheckpointMark that = (PingCheckpointMark) other;
return Objects.equals(this.oldestMessageTimestamp, that.oldestMessageTimestamp)
&& Objects.deepEquals(this.outputs, that.outputs);
}
else {
return false;
}
}
}
#VisibleForTesting
static class UnboundedPingSource extends UnboundedSource<String, PingCheckpointMark> {
private final WindowsRead spec;
public UnboundedPingSource(WindowsRead spec)
{
this.spec = spec;
}
#Override
public UnboundedReader<String> createReader(
PipelineOptions options, PingCheckpointMark checkpointMark)
{
return new UnboundedPingReader(this, checkpointMark);
}
#Override
public List<UnboundedPingSource> split(int desiredNumSplits, PipelineOptions options)
{
// Don't really need to ever split the ping source, so we should just have one per destination
return Collections.singletonList(new UnboundedPingSource(spec));
}
#Override
public void populateDisplayData(DisplayData.Builder builder)
{
spec.populateDisplayData(builder);
}
#Override
public Coder<PingCheckpointMark> getCheckpointMarkCoder()
{
return SerializableCoder.of(PingCheckpointMark.class);
}
#Override
public Coder<String> getOutputCoder()
{
return StringUtf8Coder.of();
}
}
#VisibleForTesting
static class UnboundedPingReader extends UnboundedSource.UnboundedReader<String> {
private final UnboundedPingSource source;
private String current;
private Instant currentTimestamp;
private final PingCheckpointMark checkpointMark;
private BufferedReader processOutput;
private Process process;
private boolean finishedPings;
private int maxCount = 5;
private static AtomicInteger currCount = new AtomicInteger(0);
public UnboundedPingReader(UnboundedPingSource source, PingCheckpointMark checkpointMark)
{
this.finishedPings = false;
this.source = source;
this.current = null;
if (checkpointMark != null) {
this.checkpointMark = checkpointMark;
}
else {
this.checkpointMark = new PingCheckpointMark();
}
}
#Override
public boolean start() throws IOException
{
WindowsRead spec = source.spec;
String cmd = createCommand(spec.pingConfiguration().getPingCount(), spec.pingConfiguration().getDestination());
try {
ProcessBuilder builder = new ProcessBuilder(cmd.split(" "));
builder.redirectErrorStream(true);
process = builder.start();
processOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));
return advance();
} catch (Exception e) {
throw new IOException(e);
}
}
private String createCommand(int count, String dest){
StringBuilder builder = new StringBuilder("ping");
String countParam = "";
if (count <= 0){
countParam = "-t";
}
else{
countParam += "-n " + count;
}
return builder.append(" ").append(countParam).append(" ").append(dest).toString();
}
#Override
public boolean advance() throws IOException
{
String line = processOutput.readLine();
// Ignore empty/null lines
if (line == null || line.isEmpty()) {
line = processOutput.readLine();
}
// Ignore the 'Pinging <dest> with 32 bytes of data' line
if (line.contains("Pinging " + source.spec.pingConfiguration().getDestination())) {
line = processOutput.readLine();
}
// If the pings have finished, ignore
if (finishedPings) {
return false;
}
// If this is the start of the statistics, the pings are done and we can just exit
if (line.contains("statistics")) {
finishedPings = true;
}
current = line;
currentTimestamp = Instant.now();
checkpointMark.add(current, currentTimestamp);
if (currCount.incrementAndGet() == maxCount){
currCount.set(0);
return false;
}
return true;
}
#Override
public void close() throws IOException
{
if (process != null) {
process.destroy();
if (process.isAlive()) {
process.destroyForcibly();
}
}
}
#Override
public Instant getWatermark()
{
return checkpointMark.oldestMessageTimestamp;
}
#Override
public UnboundedSource.CheckpointMark getCheckpointMark()
{
return checkpointMark;
}
#Override
public String getCurrent()
{
if (current == null) {
throw new NoSuchElementException();
}
return current;
}
#Override
public Instant getCurrentTimestamp()
{
if (current == null) {
throw new NoSuchElementException();
}
return currentTimestamp;
}
#Override
public UnboundedPingSource getCurrentSource()
{
return source;
}
}
public static class WindowsRead extends PingCmd.Read {
private final PingArguments pingConfig;
private WindowsRead(PingArguments pingConfig)
{
this.pingConfig = pingConfig;
}
public Builder builder()
{
return new WindowsRead.Builder(this);
}
PingArguments pingConfiguration()
{
return pingConfig;
}
public WindowsRead withPingArguments(PingArguments configuration)
{
checkArgument(configuration != null, "configuration can not be null");
return builder().setPingArguments(configuration).build();
}
#Override
public PCollection<String> expand(PBegin input)
{
org.apache.beam.sdk.io.Read.Unbounded<String> unbounded =
org.apache.beam.sdk.io.Read.from(new UnboundedPingSource(this));
return input.getPipeline().apply(unbounded);
}
#Override
public void populateDisplayData(DisplayData.Builder builder)
{
super.populateDisplayData(builder);
pingConfiguration().populateDisplayData(builder);
}
static class Builder {
private PingArguments config;
Builder()
{
}
private Builder(WindowsRead source)
{
this.config = source.pingConfiguration();
}
WindowsRead.Builder setPingArguments(PingArguments config)
{
this.config = config;
return this;
}
WindowsRead build()
{
return new WindowsRead(this.config);
}
}
#Override
public int hashCode()
{
return Objects.hash(pingConfig);
}
}
One thing I notice in your code is that advance() always returns True. The watermark only advances on bundle completion, and I think it's runner-dependent whether a runner will ever complete a bundle if advance ever never returns False. You could try returning False after a bounded amount of time/number of pings.
You could also consider re-writing this as an SDF.

Thread doesn't terminate upon the condition, Producer-consumer threads

I would like to implement rather simple task. There are 2 queues (both have limited capacity): BlockingQueue<String> source and BlockingQueue<String> destination. There are 2 types of threads: Producer producer produces a message and stores at the BlockingQueue<String> source. The second - Replacer replacer picks from the source, transforms a message and inserts it into the BlockingQueue<String> destination.
Two questions/issues:
I am not sure that I have correctly implemented the following requirement: transfer messages from the source to destination if the source is not empty and destination is not full.
After finishing my program, there is a still running thread called - "Signal Dispatcher". How can I terminate it properly? My program doesn't terminate properly.
Here are the implementations of the relative entities:
Implementation of the source/destination queues.
public class BlockingQueueImpl<E> implements BlockingQueue<E> {
private volatile Queue<E> storage = new PriorityQueue<>();
private volatile int capacity;
private volatile int currentNumber;
public BlockingQueueImpl(int capacity) {
this.capacity = capacity;
this.storage = new PriorityQueue<E>(capacity);
}
#Override
public synchronized void offer(E element) {
while (isFull()) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
currentNumber++;
storage.add(element);
notifyAll();
}
#Override
public synchronized E poll() {
while (isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
currentNumber--;
notifyAll();
return storage.poll();
}
#Override
public int size() {
return capacity;
}
public synchronized boolean isFull(){
return currentNumber > capacity;
}
public synchronized boolean isEmpty(){
return currentNumber == 0;
}
}
Implementation of the producer
public class Producer implements Runnable {
BlockingQueue<String> source;
String threadName;
public Producer(BlockingQueue<String> source, String threadName) {
this.source = source;
this.threadName = threadName;
}
#Override
public void run() {
while (!source.isFull()) {
source.offer(Utilities.generateMessage(threadName));
}
}
}
Implementation of the consumer
public class Replacer implements Runnable {
BlockingQueue<String> source;
BlockingQueue<String> destination;
String threadName;
public Replacer(BlockingQueue<String> source,
BlockingQueue<String> destination,
String threadName) {
this.source = source;
this.destination = destination;
this.threadName = threadName;
}
public synchronized void replace() {
destination.offer(Utilities.transformMessage(threadName, source.poll()));
}
private boolean isRunning() {
return (!destination.isFull()) && (!source.isEmpty());
}
#Override
public void run() {
while (isRunning()) {
replace();
}
}
}
And helper class
public class Utilities {
public static final int NUMBER_OF_PRODUCER_THREADS = 3;
public static final int NUMBER_OF_REPLACER_THREADS = 1000;
public static final int NUMBER_OF_MESSAGES_TO_READ = 1000;
public static final int STORAGE_CAPACITY = 100;
public static String transformMessage(String threadName, String messageToTransform) {
String[] splittedString = messageToTransform.split(" ");
String newMessage = "Thread #" + threadName + " transferred message " + splittedString[splittedString.length - 1];
return newMessage;
}
public static String generateMessage(String threadName) {
return "Thread #" + threadName + " generated message #" + threadName;
}
public static void spawnDaemonThreads(String threadName,
int numberOfThreadsToSpawn,
BlockingQueue<String> source,
BlockingQueue<String> destination) {
if (destination == null) {
for (int i = 1; i < numberOfThreadsToSpawn + 1; i++) {
String name = threadName + i;
Producer producer = new Producer(source, name);
Thread threadProducer = new Thread(producer);
threadProducer.setName(name);
threadProducer.setDaemon(true);
threadProducer.start();
}
} else {
for (int i = 1; i < numberOfThreadsToSpawn + 1; i++) {
String name = threadName + i;
Replacer replacer = new Replacer(source, destination, name);
Thread threadProducer = new Thread(replacer);
threadProducer.setName(name);
threadProducer.setDaemon(true);
threadProducer.start();
}
}
}
}
Main class:
public class Main {
public static void main(String[] args) {
BlockingQueue<String> source = new BlockingQueueImpl<>(Utilities.STORAGE_CAPACITY);
BlockingQueue<String> destination = new BlockingQueueImpl<>(Utilities.STORAGE_CAPACITY);
// Create, configure and start PRODUCER threads.
Utilities.spawnDaemonThreads("Producer", Utilities.NUMBER_OF_PRODUCER_THREADS, source, null);
// Create, configure and start REPLACER threads.
Utilities.spawnDaemonThreads("Replacer", Utilities.NUMBER_OF_REPLACER_THREADS, source, destination);
// Read NUMBER_OF_MESSAGES_TO_READ from destination.
for (int i = 1; (i < Utilities.NUMBER_OF_MESSAGES_TO_READ) && !destination.isEmpty(); i++) {
System.out.println(destination.poll());
}
}
}
Here is working code.
/**
* Class {#code BlockingQueueImpl} is the implementation of the Blocking Queue.
* This class provides thread-safe operations
* {#code public void offer(E element)} and {#code public E poll()}
*/
public class BlockingQueueImpl<E> implements BlockingQueue<E> {
private volatile Queue<E> storage = new PriorityQueue<>();
private volatile int capacity;
private volatile int currentNumber;
public BlockingQueueImpl(int capacity) {
this.capacity = capacity;
this.storage = new PriorityQueue<E>(capacity);
}
#Override
public synchronized void offer(E element) {
while (isFull()) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.add(element);
currentNumber++;
notifyAll();
}
#Override
public synchronized E poll() {
E polledElement;
while (isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notifyAll();
polledElement = storage.poll();
currentNumber--;
return polledElement;
}
#Override
public int size() {
return capacity;
}
public synchronized boolean isFull(){
return currentNumber >= capacity;
}
public synchronized boolean isEmpty(){
return currentNumber == 0;
}
}
public class Producer implements Runnable {
BlockingQueue<String> source;
String threadName;
public Producer(BlockingQueue<String> source, String threadName) {
this.source = source;
this.threadName = threadName;
}
#Override
public void run() {
while (!source.isFull()) {
source.offer(Utilities.generateMessage(threadName));
}
}
}
public class Replacer implements Runnable {
BlockingQueue<String> source;
BlockingQueue<String> destination;
String threadName;
public Replacer(BlockingQueue<String> source,
BlockingQueue<String> destination,
String threadName) {
this.source = source;
this.destination = destination;
this.threadName = threadName;
}
public synchronized void replace() {
destination.offer(Utilities.transformMessage(threadName, source.poll()));
}
//Continue execution of a thread if a destination is not full and source is not empty.
private boolean isRunning() {
return (!destination.isFull()) && (!source.isEmpty());
}
#Override
public void run() {
while (isRunning()) {
replace();
}
}
}
public class Utilities {
public static final int NUMBER_OF_PRODUCER_THREADS = 3;
public static final int NUMBER_OF_REPLACER_THREADS = 1000;
public static final int NUMBER_OF_MESSAGES_TO_READ = 1000;
public static final int STORAGE_CAPACITY = 100;
public static String transformMessage(String threadName, String messageToTransform) {
String[] splittedString = messageToTransform.split(" ");
String newMessage = "Thread #" + threadName + " transferred message " + splittedString[splittedString.length - 1];
return newMessage;
}
public static String generateMessage(String threadName) {
return "Thread #" + threadName + " generated message #" + threadName;
}
public static void spawnDaemonThreads(String threadName,
int numberOfThreadsToSpawn,
BlockingQueue<String> source,
BlockingQueue<String> destination) {
if (destination == null) {
for (int i = 1; i < numberOfThreadsToSpawn + 1; i++) {
String name = threadName + i;
Producer producer = new Producer(source, name);
Thread threadProducer = new Thread(producer);
threadProducer.setName(name);
threadProducer.setDaemon(true);
threadProducer.start();
}
} else {
for (int i = 1; i < numberOfThreadsToSpawn + 1; i++) {
String name = threadName + i;
Replacer replacer = new Replacer(source, destination, name);
Thread threadProducer = new Thread(replacer);
threadProducer.setName(name);
threadProducer.setDaemon(true);
threadProducer.start();
}
}
}
}

Java Threads with ConcurrentModificationException

I'm currently working on my first multithreaded software - a program, which calculates prime numbers...
Basically I create n (number of Threads) runnables. These runnables are added to an ArrayList. They check, whether a number is a prime. If the number is a prime I add it into an long array for later use. Since I want the primes to be in correct order in this array I need specific Threads to wait for others. I do this by looping through the ArrayList (see above) and wait for the threads, which check a lower number.
After a thread is done I want to remove it from the given ArrayList, but I cant since the other threads are still looping through it (This is the reason why the ConcurrentModificationException occurs I guess - This is my first time working with threads...).
I honestly hope that any of you guys can help me :)
Thank your really much!
Matthias
My runnable class (I just create four objects of this class in the main method):
import java.util.ArrayList;
public class PrimeRunnable implements Runnable {
//Static Util
public static ArrayList<PrimeRunnable> runningThreads = new ArrayList<PrimeRunnable>();
public static long[] primes;
public static int nextFreeIndex = 1;
public static long nextPossiblePrime = 3;
//Object specific
private long numberToCheck;
private Thread primeThread;
private String threadName;
private long threadID;
public PrimeRunnable() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
runningThreads.add(this);
}
#Override
public void run() {
boolean isPrime = true;
double sqrtOfPossiblePrime = Math.sqrt(numberToCheck);
long lastDevider = 0;
for(int index = 0; index < nextFreeIndex; index++) {
lastDevider = primes[index];
if(numberToCheck%primes[index] == 0) {
isPrime = false;
break;
}
if(primes[index] > sqrtOfPossiblePrime) {
break;
}
}
while(lastDevider < sqrtOfPossiblePrime) {
lastDevider += 1;
if(numberToCheck%lastDevider == 0) {
isPrime = false;
break;
}
}
if(isPrime) {
//Wait for lower Threads.
for(PrimeRunnable runnable : runningThreads) {
if(runnable.getThreadID() < this.getThreadID()) {
try {
runnable.primeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
primes[nextFreeIndex] = numberToCheck;
increaseNextFreeIndex();
System.out.println(numberToCheck);
}
runningThreads.remove(this);
}
public void start() {
if(primeThread == null) {
primeThread = new Thread(this, threadName);
}
primeThread.start();
}
public void reset() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
//No need to readd into runningThread, since we only manipulate an already existing object.
primeThread = new Thread(this, threadName);
primeThread.start();
}
public static void setUpperBorder(int upperBorder) {
if(primes == null) {
primes = new long[upperBorder];
primes[0] = 2;
} else {
System.err.println("You are not allowed to set the upper border while running.");
}
}
public long getNumberToCheck() {
return numberToCheck;
}
private void increaseNextPossiblePrime() {
nextPossiblePrime += 2;
}
private void increaseNextFreeIndex() {
nextFreeIndex += 2;
}
public long getThreadID() {
return threadID;
}
public boolean isAlive() {
return primeThread.isAlive();
}
}
I was able to replicate the issue and fix it using Java implementation of a concurrent list CopyOnWriteArrayList
Here's my main class
public class PrimeRunnableMain {
public static void main(String[] args) {
PrimeRunnable.setUpperBorder(10);
PrimeRunnable primeRunnable1 = new PrimeRunnable();
PrimeRunnable primeRunnable2 = new PrimeRunnable();
PrimeRunnable primeRunnable3 = new PrimeRunnable();
PrimeRunnable primeRunnable4 = new PrimeRunnable();
primeRunnable1.start();
primeRunnable2.start();
primeRunnable3.start();
primeRunnable4.start();
}
}
and here's PrimeRunnable
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class PrimeRunnable implements Runnable {
// Static Util
public static List<PrimeRunnable> runningThreads = new CopyOnWriteArrayList<PrimeRunnable>();
public static long[] primes;
public static int nextFreeIndex = 1;
public static long nextPossiblePrime = 3;
// Object specific
private long numberToCheck;
private Thread primeThread;
private String threadName;
private long threadID;
public PrimeRunnable() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
runningThreads.add(this);
}
#Override
public void run() {
boolean isPrime = true;
double sqrtOfPossiblePrime = Math.sqrt(numberToCheck);
long lastDevider = 0;
for (int index = 0; index < nextFreeIndex; index++) {
lastDevider = primes[index];
if (numberToCheck % primes[index] == 0) {
isPrime = false;
break;
}
if (primes[index] > sqrtOfPossiblePrime) {
break;
}
}
while (lastDevider < sqrtOfPossiblePrime) {
lastDevider += 1;
if (numberToCheck % lastDevider == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
// Wait for lower Threads.
for (PrimeRunnable runnable : runningThreads) {
if (runnable.getThreadID() < this.getThreadID()) {
try {
runnable.primeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
primes[nextFreeIndex] = numberToCheck;
increaseNextFreeIndex();
System.out.println(numberToCheck);
}
runningThreads.remove(this);
}
public void start() {
if (primeThread == null) {
primeThread = new Thread(this, threadName);
}
primeThread.start();
}
public void reset() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
// No need to readd into runningThread, since we only manipulate an
// already existing object.
primeThread = new Thread(this, threadName);
primeThread.start();
}
public static void setUpperBorder(int upperBorder) {
if (primes == null) {
primes = new long[upperBorder];
primes[0] = 2;
} else {
System.err
.println("You are not allowed to set the upper border while running.");
}
}
public long getNumberToCheck() {
return numberToCheck;
}
private void increaseNextPossiblePrime() {
nextPossiblePrime += 2;
}
private void increaseNextFreeIndex() {
nextFreeIndex += 2;
}
public long getThreadID() {
return threadID;
}
public boolean isAlive() {
return primeThread.isAlive();
}
}
What about a PrimeListener class that contains a synchronized method publishPrime that inserts the prime in the correct position in the list? Inserting at the right position into the list should not take too much time, if you start at the last index of a LinkedList.
Alternatively you could also insert it into a SortedSet (implementation: TreeSet). I presume you don't want any duplicate primes anyway. In that case synchronizedSortedSet may be directly used instead of the listener.
Note that you still seem rather stuck on lower level structures. When programming concurrently on Java it pays off to use the higher level constructs (executors, futures, concurrent queue's etc. etc.).
The main distinction between fail-fast and fail-safe iterators is
whether or not the collection can be modified while it is being
iterated. Fail-safe iterators allow this; fail-fast iterators do not.
Fail-fast iterators operate directly on the collection itself. During
iteration, fail-fast iterators fail as soon as they realize that the
collection has been modified (i.e., upon realizing that a member has
been added, modified, or removed) and will throw a
ConcurrentModificationException. Some examples include ArrayList,
HashSet, and HashMap (most JDK1.4 collections are implemented to be
fail-fast). Fail-safe iterates operate on a cloned copy of the
collection and therefore do not throw an exception if the collection
is modified during iteration. Examples would include iterators
returned by ConcurrentHashMap or CopyOnWriteArrayList.

Why inner class method cannot synchronized the object in outer class?

I encountered a problem:Will inner class method cannot synchronized the object in outer class? A answer from stackoverflow told me : No. But I really want to know the reason.
For example:
I designed a thread pool with at most 5 threads to do work.
public class ThreadPool{
// Ignore the Task class
private LinkedList<Task> tasks;
Executor[] executors = new Executor[5];
private static ThreadPool pool = null;
private ThreadPool() {
tasks = new LinkedList<Task>();
for (int i = 0; i < 5; i++) {
executors[i] = new Executor(i);
}
}
public static ThreadPool getInstance() {
if (pool == null) {
pool = new ThreadPool();
}
return pool;
}
public void addTask(Task task) {
/** igore code here*/
}
private class Executor extends Thread {
private int i;
public Executor(int i) {
this.i = i;
start();
}
public void run() {
Task task = null;
synchronized (tasks) {
if (tasks.size() == 0) {
System.out.println("tasks's size is : " + tasks.size());
try {
while (tasks.size() == 0) {
tasks.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (tasks.size() > 0)
task = tasks.removeFirst();
}
if (task != null) {
/** ignore code here */
}
}
}
}
Unfortunately, the synchronized doesn't work. But when I put the synchronized block into
synchronized (ThreadPool.this) {
...
}
it works.
So, i want to know why inner class method cannot synchronized the object in outer class.
Hope for a detailed answer.

Asynchronous Iterator

I have the following code:
while(slowIterator.hasNext()) {
performLengthTask(slowIterator.next());
}
Because both iterator and task are slow it makes sense to put those into separate threads. Here is a quick and dirty attempt for an Iterator wrapper:
class AsyncIterator<T> implements Iterator<T> {
private final BlockingQueue<T> queue = new ArrayBlockingQueue<T>(100);
private AsyncIterator(final Iterator<T> delegate) {
new Thread() {
#Override
public void run() {
while(delegate.hasNext()) {
queue.put(delegate.next()); // try/catch removed for brevity
}
}
}.start();
}
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
return queue.take(); // try/catch removed for brevity
}
// ... remove() throws UnsupportedOperationException
}
However this implementation lacks support for "hasNext()". It would be ok of course for the hasNext() method to block until it knows whether to return true or not. I could have a peek object in my AsyncIterator and I could change hasNext() to take an object from the queue and have next() return this peek. But this would cause hasNext() to block indefinitely if the delegate iterator's end has been reached.
Instead of utilizing the ArrayBlockingQueue I could of course do thread communication myself:
private static class AsyncIterator<T> implements Iterator<T> {
private final Queue<T> queue = new LinkedList<T>();
private boolean delegateDone = false;
private AsyncIterator(final Iterator<T> delegate) {
new Thread() {
#Override
public void run() {
while (delegate.hasNext()) {
final T next = delegate.next();
synchronized (AsyncIterator.this) {
queue.add(next);
AsyncIterator.this.notify();
}
}
synchronized (AsyncIterator.this) {
delegateDone = true;
AsyncIterator.this.notify();
}
}
}.start();
}
#Override
public boolean hasNext() {
synchronized (this) {
while (queue.size() == 0 && !delegateDone) {
try {
wait();
} catch (InterruptedException e) {
throw new Error(e);
}
}
}
return queue.size() > 0;
}
#Override
public T next() {
return queue.remove();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
However all the extra synchronizations, waits and notifys don't really make the code any more readable and it is easy to hide a race condition somewhere.
Any better ideas?
Update
Yes I do know about common observer/observable patterns. However the usual implementations don't foresee an end to the flow of data and they are not iterators.
I specifically want an iterator here, because actually the above mentioned loop exists in an external library and it wants an Iterator.
This is a tricky one, but I think I got the right answer this time. (I deleted my first answer.)
The answer is to use a sentinel. I haven't tested this code, and I removed try/catches for clarity:
public class AsyncIterator<T> implements Iterator<T> {
private BlockingQueue<T> queue = new ArrayBlockingQueue<T>(100);
private T sentinel = (T) new Object();
private T next;
private AsyncIterator(final Iterator<T> delegate) {
new Thread() {
#Override
public void run() {
while (delegate.hasNext()) {
queue.put(delegate.next());
}
queue.put(sentinel);
}
}.start();
}
#Override
public boolean hasNext() {
if (next != null) {
return true;
}
next = queue.take(); // blocks if necessary
if (next == sentinel) {
return false;
}
return true;
}
#Override
public T next() {
T tmp = next;
next = null;
return tmp;
}
}
The insight here is that hasNext() needs to block until the next item is ready. It also needs some kind of quit condition, and it can't use an empty queue or a boolean flag for that because of threading issues. A sentinel solves the problem without any locking or synchronization.
Edit: cached "next" so hasNext() can be called more than once.
Or save yourself the headache and use RxJava:
import java.util.Iterator;
import rx.Observable;
import rx.Scheduler;
import rx.observables.BlockingObservable;
import rx.schedulers.Schedulers;
public class RxAsyncIteratorExample {
public static void main(String[] args) throws InterruptedException {
final Iterator<Integer> slowIterator = new SlowIntegerIterator(3, 7300);
// the scheduler you use here will depend on what behaviour you
// want but io is probably what you want
Iterator<Integer> async = asyncIterator(slowIterator, Schedulers.io());
while (async.hasNext()) {
performLengthTask(async.next());
}
}
public static <T> Iterator<T> asyncIterator(
final Iterator<T> slowIterator,
Scheduler scheduler) {
final Observable<T> tObservable = Observable.from(new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return slowIterator;
}
}).subscribeOn(scheduler);
return BlockingObservable.from(tObservable).getIterator();
}
/**
* Uninteresting implementations...
*/
public static void performLengthTask(Integer integer)
throws InterruptedException {
log("Running task for " + integer);
Thread.sleep(10000l);
log("Finished task for " + integer);
}
private static class SlowIntegerIterator implements Iterator<Integer> {
private int count;
private final long delay;
public SlowIntegerIterator(int count, long delay) {
this.count = count;
this.delay = delay;
}
#Override
public boolean hasNext() {
return count > 0;
}
#Override
public Integer next() {
try {
log("Starting long production " + count);
Thread.sleep(delay);
log("Finished long production " + count);
}
catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return count--;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private static final long startTime = System.currentTimeMillis();
private static void log(String s) {
double time = ((System.currentTimeMillis() - startTime) / 1000d);
System.out.println(time + ": " + s);
}
}
Gives me:
0.031: Starting long production 3
7.332: Finished long production 3
7.332: Starting long production 2
7.333: Running task for 3
14.633: Finished long production 2
14.633: Starting long production 1
17.333: Finished task for 3
17.333: Running task for 2
21.934: Finished long production 1
27.334: Finished task for 2
27.334: Running task for 1
37.335: Finished task for 1

Categories

Resources