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

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();
}
}
}
}

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.

Multithreading in Java ( Bank queue)

I try to develep simulates a bank branch.I want to generate a new customer and add the customer to the queue(or ArrayList). If there are available tellers (there are 2 tellers), remove customer from the list and assign them to tellers. I used 2 threads, first one is generate customer and add to the list. Second one is belongs to tellers. I have some problem.
Customer class
public class Customer {
private int customerID;
private int processTime;
ArrayList<Integer> customerIDList = new ArrayList<>();
ArrayList<Integer> processTimeList = new ArrayList<>();
public int getCustomerID() {
return customerID;
}
public void setCustomerID(int customerID) {
this.customerID = customerID;
}
public int getProcessTime() {
return processTime;
}
public void setProcessTime(int processTime) {
this.processTime = processTime;
}
public ArrayList<Integer> getCustomerIDList() {
return customerIDList;
}
public void setCustomerIDList(ArrayList<Integer> customerIDList) {
this.customerIDList = customerIDList;
}
public ArrayList<Integer> getProcessTimeList() {
return processTimeList;
}
public void setProcessTimeList(ArrayList<Integer> processTimeList) {
this.processTimeList = processTimeList;
}
}
Teller class
public class Teller {
private boolean status = true;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
}
CustomerThread class
public class CustomerThread extends Thread {
Customer c = new Customer();
Methods method = new Methods();
#Override
public void run() {
for(int i = 0; i < 10; i++) {
try {
c.getCustomerIDList().add(i+1);
c.getProcessTimeList().add(method.generateProcessTime());
System.out.println("ID : " + c.getCustomerIDList().get(i) + " - Process Time : " + c.getProcessTimeList().get(i));
Thread.sleep(100);
}
catch (InterruptedException ex) {
Logger.getLogger(CustomerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Between to customers 100 msec
TellerThread class
public class TellerThread extends Thread{
Customer c1 = new Customer();
Teller teller1 = new Teller();
Teller teller2 = new Teller();
#Override
public void run() {
try {
Thread.sleep(100);
while(c1.getProcessTimeList().isEmpty()) {
if(teller1.isStatus()) {
teller1.setStatus(false);
System.out.println("Customer " + c1.getCustomerIDList().get(0) + " came teller1.");
c1.getCustomerIDList().remove(0);
Thread.sleep(c1.getProcessTimeList().get(0));
System.out.println("Teller 1 is waiting of " + c1.getProcessTimeList().get(0) + " msec.");
c1.getProcessTimeList().remove(0);
teller1.setStatus(true);
System.out.println("Teller 1 is Available.");
}
else if(teller2.isStatus()) {
teller2.setStatus(false);
System.out.println("Customer " + c1.getCustomerIDList().get(0) + " came teller2.");
c1.getCustomerIDList().remove(0);
Thread.sleep(c1.getProcessTimeList().get(0));
System.out.println("Teller 2 is waiting of " + c1.getProcessTimeList().get(0) + " msec.");
c1.getProcessTimeList().remove(0);
teller2.setStatus(true);
System.out.println("Teller 2 is Available");
}
else {
System.out.println("There is no customer..");
}
}
} catch (InterruptedException ex) {
Logger.getLogger(TellerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
and Test class
public class Test {
public static void main(String[] args) {
CustomerThread ct = new CustomerThread();
TellerThread tt = new TellerThread();
ExecutorService es = Executors.newCachedThreadPool();
es.execute(ct);
es.execute(tt);
es.shutdown();
}
}
When I execute this codes, I see only customers on the output. There are no tellers process. How can I fix this?

Unexpected behaviour in threadsafe class

I try to make a thread safe class which allows to follow the scan of something. My class is:
import java.util.concurrent.atomic.AtomicInteger;
public class ScanInProgress {
private final Integer scanId;
private final int nbScans;
private AtomicInteger nbResponses = new AtomicInteger(0);
private AtomicInteger nbErrors = new AtomicInteger(0);
public ScanInProgress(Integer scanId, int nbSites) {
this.scanId = scanId;
this.nbScans = nbSites;
}
public Integer getScanId() {
return scanId;
}
public boolean addSuccess() {
addResponse();
return isDone();
}
public boolean addError() {
addResponse();
nbErrors.incrementAndGet();
return isDone();
}
private void addResponse() {
nbResponses.incrementAndGet();
}
private boolean isDone() {
return nbResponses.get() == nbScans;
}
public int getNbSuccesses() {
return nbResponses.get() - nbErrors.get();
}
public int getNbResponses() {
return nbResponses.get();
}
}
I have the following unit tests class:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ScanInProgressTest {
#Test
public void testConcurrency() throws Exception {
// given
Integer scanId = 1;
int nbScans = 500_000;
ScanInProgress scanInProgress = new ScanInProgress(scanId, nbScans);
// when
for (int i = 1; i <= nbScans / 2; i++) {
new AddError(scanInProgress).start();
new AddSuccess(scanInProgress).start();
}
Thread.sleep(1000);
// then
assertEquals(nbScans, scanInProgress.getNbResponses());
assertEquals(nbScans / 2, scanInProgress.getNbSuccesses());
}
private class AddError extends Thread {
private ScanInProgress scanInProgress;
public AddError(ScanInProgress scanInProgress) {
this.scanInProgress = scanInProgress;
}
#Override
public void run() {
int before = scanInProgress.getNbResponses();
scanInProgress.addError();
int after = scanInProgress.getNbResponses();
assertTrue("Add error: before=" + before + ", after=" + after, before < after);
}
}
private class AddSuccess extends Thread {
private ScanInProgress scanInProgress;
public AddSuccess(ScanInProgress scanInProgress) {
this.scanInProgress = scanInProgress;
}
#Override
public void run() {
int beforeResponses = scanInProgress.getNbResponses();
int beforeSuccesses = scanInProgress.getNbSuccesses();
scanInProgress.addSuccess();
int afterResponses = scanInProgress.getNbResponses();
int afterSuccesses = scanInProgress.getNbSuccesses();
assertTrue("Add success responses: before=" + beforeResponses + ", after=" + afterResponses, beforeResponses < afterResponses);
assertTrue("Add success successes: before=" + beforeSuccesses + ", after=" + afterSuccesses, beforeSuccesses < afterSuccesses);
}
}
}
When I run my test I can see regularly this error in logs:
Exception in thread "Thread-14723" java.lang.AssertionError: Add success successes: before=7362, after=7362
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.assertTrue(Assert.java:41)
The assertion lets me think that when I call the method scanInProgress.addSuccess() and then scanInProgress.getNbSuccesses(), the instruction in first method nbResponses.incrementAndGet() is not yet acknowledged whereas the instruction in second method nbResponses.get() returns something.
What can I do to correct this ?
As far as I unsterstand the problem I think you need to use locks. Before you get or set an variable you need to aquire a lock. This way a variable can't be set and read at the same time. You get something like the code below.
public final static Object LOCK = new Object();
private int yourvariable;
public void setVar(int var){
synchronized(LOCK){
yourvariable = var;
}
}
public int getVar(){
int toReturn;
synchronized(LOCK){
toReturn = yourvariable;
}
return toReturn;
}
note: If your ScanInProgessClass is the only the ScanInProgressClass class, you can use this instead of a LOCK object.

Java Multi threading

I have to use two threads such that one thread prints all the odd numbers less than 10, and the other to print even numbers less than 10 and the final output should be in sequence.
I have achieved this as follows. I want to do the same using synchronized methods? How to do it?
class printodd extends Thread{
public void run() {
super.run();
for(int i=0;i<10;i=i+2){
System.out.println("even "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class printeven extends Thread{
public void run() {
super.run();
for(int i=1;i<10;i=i+2)
{
System.out.println("odd "+i);
try {
Thread.sleep(1050);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PrintNumSeq{
public static void main(String[] args) {
printodd p=new printodd();
printeven e=new printeven();
e.start();
p.start();
}
}
Try this
public class PrintNumSeq extends Thread {
static Object lock = new Object();
static int n;
int even;
PrintNumSeq(int r) {
this.even = r;
}
public void run() {
try {
synchronized (lock) {
for (;;) {
while ((n & 1) != even) {
lock.wait();
}
n++;
lock.notify();
if (n > 10) {
break;
}
System.out.println(n);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new PrintNumSeq(1).start();
new PrintNumSeq(0).start();
}
}
output
1
2
3
4
5
6
7
8
9
10
public class SequentialThreadPrinter {
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(0);
EvenThread even = new EvenThread("even", counter);
OddThread odd = new OddThread("odd", counter);
even.start();
odd.start();
}
}
private static class EvenThread extends Thread {
private String name;
private AtomicInteger counter;
public EvenThread(String name, AtomicInteger counter) {
this.name = name;
this.counter = counter;
}
public void run() {
do {
synchronized (counter) {
if (counter.get() % 2 == 0) {
System.out.println("Thread is " + name + ", Counter is = " + counter.getAndAdd(1));
counter.notifyAll();
} else {
try {
counter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} while (counter.get() <= 10);
}
}
private static class OddThread extends Thread {
private String name;
private AtomicInteger counter;
public OddThread(String name, AtomicInteger counter) {
this.name = name;
this.counter = counter;
}
public void run() {
do {
synchronized (counter) {
if (counter.get() % 2 != 0) {
System.out.println("Thread is " + name + ", Counter is = " + counter.getAndAdd(1));
counter.notifyAll();
} else {
try {
counter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} while (counter.get() <= 10);
}
}
}
Hi in here you have to use java synchronization. Basically synchronization is Java mechanism shared between thread which will block all other threads while one is running. By doing so in your case you can print them sequentially.
You can read the following tutorial to understand it
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Be careful though while you use it, because not using carefully might create a deadlock
http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
You could achieve this by having the threads acquire a common lock in order to be allowed to print anything.
The "lock" could be some singleton like:
public class Lock {
private static Lock instance;
private static boolean inUse = false;
public static Lock getInstance() {
if(instance == null) {
instance = new Lock();
}
return instance;
}
public boolean acquireLock() {
boolean rv = false;
if(inUse == false) {
inUse = true;
rv = true;
}
return rv;
}
public void releaseLock() {
inUse = false;
}
}
Whenever a thread wants to print it has to call acquireLock() and if it returns true, then it can print. If it returns false, then it has to wait until it returns true. Immediately after printing the thread calls releaseLock() so that the Lock is freed.
I didn't test this code, so use it at your own risk. I just typed it up really quick as it was the idea I was thinking of.
You can read more about locks and their use in synchronization here: http://en.wikipedia.org/wiki/Lock_(computer_science)

how to terminate retrieval from a blocking queue

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.

Categories

Resources