Java Blocking Q test stops executing - java

I have the following test code for learning purposes, in which I am trying to run a producer and a consumer threads running endlessly on a blocking Q.
For some reason which I cannot understand, the output is as follows:
Produced 3001
Q puts 3001
put: Q size = 1
Produced 3002
Q puts 3002
put: Q size = 2
Q takes 3001
take: Q size = 1
Consumed 3001
The code is as follows:
#Getter #Setter #NoArgsConstructor
public class MyBlockingQ {
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
public Integer take() {
try {
Integer i = queue.take();
System.out.println("Q takes " + i);
System.out.println("take: Q size = " + queue.size());
return i;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
public void put(Integer produce) {
try {
System.out.println("Q puts " + produce);
queue.put(produce);
System.out.println("put: Q size = " + queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyProducer implements Runnable {
private final MyBlockingQ queue;
private Integer i = 3000;
public MyProducer(MyBlockingQ q) {
queue = q;
}
public void run() {
while (true) {
queue.put(produce());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Integer produce() {
i++;
System.out.println("Produced " + i);
return i;
}
}
public class MyConsumer implements Runnable {
private final MyBlockingQ queue;
public MyConsumer(MyBlockingQ q) {
queue = q;
}
public void run() {
while (true) {
consume(queue.take());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void consume(Integer x) {
System.out.println("Consumed " + x);
}
}
#Test
public void testBlockingQ(){
MyBlockingQ q = new MyBlockingQ();
MyProducer p1 = new MyProducer(q);
MyConsumer c1 = new MyConsumer(q);
new Thread(p1).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(c1).start();
}
I cannot understand why does the code stop executing after the last output line as shown above?
I am working with JavaSE-15 on latest VSCode.

Threads are terminated, when your test method reaches to the end. If you want your threads to run longer, you need to add more sleep time at the end of your test method.
#Test
public void testBlockingQ(){
MyBlockingQ q = new MyBlockingQ();
MyProducer p1 = new MyProducer(q);
MyConsumer c1 = new MyConsumer(q);
new Thread(p1).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(c1).start();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Related

How to effectively ping and discover all clients on a network?

The problem I am having is acquiring all reachable clients on a network.The below method returns some clients when called. In most cases other android clients.However for the PC it fails when firewall is on.Is there a more effective way to get all clients in Java/android purely or will I need to use android NDK?Any help from experts in this domain will be appreciated.Thanks in advance.
/***
* ping_JavaStyle(final int j)
* uses multi threads to enhance performance
* while pinging from 0>j<=255
* #param j
*/
private void ping_JavaStyle(final int j)
{
new Thread(new Runnable() { // new thread for parallel execution
public void run() {
try {
String testIp = prefix + String.valueOf(j);
InetAddress address = InetAddress.getByName(testIp);
String output = address.toString().substring(1);
if (address.isReachable(3000)) {
System.out.println(output + " is on the network");
ipList.add(testIp);
} else {
if (retest(testIp, 139)) {
ipList.add(testIp);
} else {
System.out.println("Not Reachable: " + output);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
After Researching some more, got this working.With help of this repo:https://github.com/stealthcopter/AndroidNetworkTools
Below code solves the problem:
** RunnableTask.Java
* Created by Kirk on 10/29/2017.
*/
public class RunnableTask implements Callable<Boolean> {
private String testIp = "";
private Boolean is_Reachable = false;
public RunnableTask(String testIp) {
this.testIp = testIp;
}
#Override
public Boolean call() throws Exception {
try {
PingResult pingResult = Ping.onAddress(this.testIp).setTimes(1).setTimeOutMillis(1500).doPing();
if (pingResult.isReachable) {
is_Reachable = true;
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
return is_Reachable;
}
}
And use in the caller method:
private static final int NTHREDS = 255;
//.......
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<Boolean>> thread_Values_list = new ArrayList<>();
for (int i = 1; i <= 255; i++) {
final int j = i;
try {
try {
String testIp = prefix + String.valueOf(j);
RunnableTask worker = new RunnableTask(testIp);
Future<Boolean> submit = executor.submit(worker);
thread_Values_list.add(submit);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
}
for (Future<Boolean> finishedThread : thread_Values_list) {
String reachable_Ip = "";
try {
if (finishedThread.get()) {
reachable_Ip = prefix + String.valueOf(finishThread_counter);
ipList.add(reachable_Ip);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finishThread_counter++;
}
executor.shutdown();
}

start simple 1-producer 2-consumers through executor service

public class SemActionPlace {
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
List<Thread> threads = new LinkedList<>();
Thread p1 = new Thread(new Producer(monitor), "P1");
p1.start();
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
c1.start();
Thread c2 = new Thread(new Consumer(monitor), "C-even");
c2.start();
threads.add(p1);
threads.add(c1);
threads.add(c2);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return monitor;
}
}
the code work just fine when I start thread through start() - join(), however, I failed to find mistake when I try to do the same through the executor service. It's important for me to save names of the threads and mutual monitor. Please, tell me how can I execute the threads through the executor service ?
The piece of code below doen't work properly. Where is mistake ?
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
Thread p1 = new Thread(new Producer(monitor), "P1");
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
Thread c2 = new Thread(new Consumer(monitor), "C-even");
ThreadPoolExecutor service = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
service.execute(p1);
service.execute(c1);
service.execute(c2);
System.out.println(service.getCompletedTaskCount());
System.out.println(service.getCompletedTaskCount());
return monitor;
}
I need one simple thing from the executor server is that I wanna that it works like simple start() - join() solution works ( first piece of code ) .
class Consumer implements Runnable {
private final SemMonitor monitor;
Consumer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
long t = System.currentTimeMillis();
long end = t + 1000;
while (System.currentTimeMillis() < end) {
consoleLog(monitor.activeThreadName,false);
if (/*monitor.semaphore.tryAcquire() && */monitor.activeThreadName.equals( Thread.currentThread().getName())) {
try {
consoleLog(String.valueOf(Thread.currentThread().getName() + " was notified "),monitor.enableLog);
monitor.semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
monitor.get(Thread.currentThread().getName());
}
try{
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer implements Runnable {
private SemMonitor monitor;
Producer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
String threadNameToWork;
Integer randNum;
long t = System.currentTimeMillis();
long end = t + 500;
while (System.currentTimeMillis() < end) {
if (monitor.semaphore.tryAcquire()) {
randNum = ((Number) (random() * 100)).intValue();
if (randNum % 2 == 0) {
threadNameToWork = "C-even";
} else {
threadNameToWork = "C-odd";
}
try {
monitor.putItem(randNum, Thread.currentThread().getName(), threadNameToWork);
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Monitor {
private double currItem;
private boolean isConsumersShouldWaitProducer = true;
private boolean isConsuming = false;
private String threadNameToWork;
synchronized void putRandNumber(double producerOutput, String producerName, String threadNameToWork) {
if (isConsumersShouldWaitProducer) {
System.out.println("Consumers wait for new Production");
}
this.threadNameToWork = threadNameToWork;
currItem = producerOutput;
System.out.println("Producer " + producerName + " putRandNumber Item: " + currItem);
if (currItem > 3) {
notifyAll();
isConsumersShouldWaitProducer = false;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void consumeRandNumber(String threadName) {
if (isConsumersShouldWaitProducer) {
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
if (isConsuming) {
try {
this.wait();
isConsuming = true;
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
switch (Thread.currentThread().getName()) {
/*switch (threadNameToWork) {*/
case "C-odd":
isConsuming = true;
if (currItem % 2 != 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case "C-even":
isConsuming = true;
if (currItem % 2 == 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
private synchronized void consumeItems(String threadName) {
isConsumersShouldWaitProducer = true;
String randNumType = "*odd/even*";
System.out.println("Consumer:" + threadName + " consumed " + randNumType + " Items = " + currItem);
notifyAll();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You want to do something with Thread name right? The thread name you created in using new Thread will not pass into ExecutorService, but this will
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("thread-%d").build()
Then
ExecutorService exec = Executors.newSingleThreadExecutor(namedThreadFactory);
Now you have thread with name as thread-1, thread-2
OR set thread name in your run() method
Thread.currentThread().setName(myName)
To make sure your thread is finished, add this before you return the monitor,
service.shutdown();
while (!service.awaitTermination(10, TimeUnit.SECONDS)) {
log.info("Awaiting completion of threads.");
}

Java : synchronizing on custom collection class

I want to have shared collection class which is filled by producer thread and output is shown by consumer thread. It's sometimes working with 0 element of the collection class but never goes further. In Eclipse I observer "DestroyJVM" thread after application freezes.
There is artificial latency on the producer to simulate "slow" producer. I don't have an idea why application is not working in sequence, like
"Producer acquires lock on collection class, adds Integer, consumer waits, producer releases lock, consumer acquires lock, consumer prints, consumer releases lock, producer acquires..." and so on.
Can anyone point out where is the mistake?
Here is my code:
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
producerThread.start();
consumerThread.start();
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 100;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max < ints.size();
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private int timeout = 100;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
while (!getInts().isFinished()) {
synchronized (getInts()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
Thread.sleep(timeout);
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null && getInts().getSize() > 0) {
int i = 0;
while (!getInts().isFinished()) {
synchronized (getInts()) {
showAtPosition(i, getInts());
i++;
try {
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
}
} else {
Thread.yield();
}
}
private void showAtPosition(int position, SharedIntegers ints) {
out.println("sharedInts[" + position + "] -> " + ints.getAtPosition(position));
}
}
EDITED: I managed to rewrite code so that it will work in the desired manner, however, producerThread and consumerThread don't exit gracefully. Any ideas why?
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
out.println("Main application started");
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
consumerThread.start();
try {
Thread.sleep(1000); // simulate that consumerThread is "anxious" to start
} catch (InterruptedException e) {
e.printStackTrace();
}
producerThread.start();
try {
consumerThread.join(); //let consumerThread finish before main()
producerThread.join(); //let producerThread finish before main()
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("Main application finished");
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 5;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max <= ints.size();
}
public synchronized boolean overflow(int i) {
return i >= max;
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private final int timeout = 500;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
synchronized (getInts()) {
while (!getInts().isFinished()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
getInts().notify();
getInts().wait();
Thread.sleep(timeout); // simulate "slow" producer
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
try {
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
out.println("Finished ProducerThread");
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null) {
synchronized (getInts()) {
int i = 0;
while (!getInts().overflow(i)) {
if (getInts().getSize() > 0) {
showAtPosition(i, getInts());
i++;
}
try {
getInts().notify();
getInts().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
out.println("Finished ConsumerThread");
}
private void showAtPosition(int position, SharedIntegers ints) {
out.println("sharedInts[" + position + "] -> " + ints.getAtPosition(position));
}
}
EDIT 2: solution found : needed to notify consumerThread from producerThread that getInts() lock can be re-acquired. The working code with my comments looks like this (added some data modification by consumerThread):
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class SyncOwnCollMain {
public static void main(String[] args) {
out.println("Main application started");
SharedIntegers ints = new SharedIntegers();
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.setInts(ints);
consumer.setInts(ints);
Thread producerThread = new Thread(producer);
producerThread.setName("ProducerThread");
Thread consumerThread = new Thread(consumer);
consumerThread.setName("ConsumerThread");
consumerThread.start();
try {
Thread.sleep(1000); // simulate that consumerThread is "anxious" to start
} catch (InterruptedException e) {
e.printStackTrace();
}
producerThread.start();
try {
consumerThread.join(); //let consumerThread finish before main()
producerThread.join(); //let producerThread finish before main()
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("Main application finished"); // here, main() thread has result produced by producerThread and consumerThread
}
}
class SharedIntegers {
private final List<Integer> ints = new ArrayList<Integer>();
private final int max = 5;
public synchronized void addAtPosition(int i, Integer integer) {
ints.add(i, integer);
}
public synchronized Integer getAtPosition(int i) {
return ints.get(i);
}
public synchronized Integer removeAtPosition(int i) {
return ints.remove(i);
}
public synchronized Integer getSize() {
return ints.size();
}
public synchronized boolean isFinished() {
return max <= ints.size();
}
public synchronized boolean overflow(int i) {
return i >= max;
}
}
class Producer implements Runnable {
private SharedIntegers ints;
private final int timeout = 500;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ProducerThread");
if (getInts() != null) {
int i = 0;
Integer integer = null;
synchronized (getInts()) {
while (!getInts().isFinished()) {
integer = i * 3;
getInts().addAtPosition(i, integer);
out.print("Producer added new integer = " + integer + " at " + i + " position");
out.println(". Will sleep now for " + timeout + " ms");
try {
getInts().notifyAll(); // notify all threads (in this case - consumer thread) that getInts() will be available for other threads to sync and other threads are legitimate to compete for locking getInts()
getInts().wait(); // release lock for getInts()
Thread.sleep(timeout); // simulate "slow" producer
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
out.println("Finished ProducerThread while() loop");
getInts().notifyAll(); // after job is done, need to notify consumer thread that it can compete to obtain getInts() lock
}
}
}
}
class Consumer implements Runnable {
private SharedIntegers ints;
public SharedIntegers getInts() {
return ints;
}
public void setInts(SharedIntegers ints) {
this.ints = ints;
}
#Override
public void run() {
out.println("Started ConsumerThread");
if (getInts() != null) {
int i = 0;
synchronized (getInts()) {
while (!getInts().overflow(i)) {
if (getInts().getSize() > 0) {
out.println(showAtPosition(i, getInts()));
increaseAtPosition(i, getInts());
out.println("After consumer increase : " + showAtPosition(i, getInts()));
i++;
}
try {
getInts().notifyAll(); // notify all threads that other threads are legitimate to compete for getInts() lock
getInts().wait(); // release getInts() lock, wait for allowance notification
} catch (InterruptedException e) {
e.printStackTrace();
}
}
out.println("Finished ConsumerThread while() loop");
}
}
}
private String showAtPosition(int position, SharedIntegers ints) {
return "sharedInts[" + position + "] -> " + ints.getAtPosition(position);
}
private void increaseAtPosition(int position, SharedIntegers ints) {
Integer increased = ints.getAtPosition(position)+1;
ints.removeAtPosition(position);
ints.addAtPosition(position, increased);
}
}
Your call to getInts().wait(); causes each Thread to wait forever, since you never call notify() , therefore your application freezes.
See the Javadoc for java.lang.Object.wait() and java.lang.Object.notify()
Inside the Producer, change
getInts().wait()
to
getInts().notify()

Producer Consumer using threads

I’m writing a program that implements the Producer Consumer problem in Java using multithreading concepts. Below are few details how I’m supposed to do it:
1) The main thread should create a buffer with capacity specified as a command line argument. The number of producer and consumer threads are also specified as command line arguments. I’m supposed to assign a unique number to each producer and consumer thread. How do I assign a unique number to producer and consumer threads?
2) The producer thread operates in an infinite loop. It produces a data item (a string) with the following format: <producer number>_<data item number>. For example the 1st data item from thread number 1 will be 1_1 and second data item from thread number 3 will be 3_2. How do create data items in such a format?
3) Then the Producer thread writes an entry into the producer log file (< producer number > “Generated” <data item>). Upon writing the log entry, it attempts to insert into the buffer. If insertion is successful, it creates an entry into the log file (<producer number> <data item> “Insertion successful”). How do I write such a code?
Below is the Java code I wrote.
import java.util.*;
import java.util.logging.*;
public class PC2
{
public static void main(String args[])
{
ArrayList<Integer> queue = new ArrayList<Integer>();
int size = Integer.parseInt(args[2]);
Thread[] prod = new Thread[Integer.parseInt(args[0])];
Thread[] cons = new Thread[Integer.parseInt(args[1])];
for(int i=0; i<prod.length; i++)
{
prod[i] = new Thread(new Producer(queue, size));
prod[i].start();
}
for(int i=0; i<cons.length; i++)
{
cons[i] = new Thread(new Consumer(queue, size));
cons[i].start();
}
}
}
class Producer extends Thread
{
private final ArrayList<Integer> queue;
private final int size;
public Producer(ArrayList<Integer> queue, int size)
{
this.queue = queue;
this.size = size;
}
public void run()
{
while(true){
for(int i=0; i<size; i++)
{
System.out.println("Produced: "+i+" by id " +Thread.currentThread().getId());
try
{
produce(i);
Thread.sleep(3000);
}
catch(Exception e)
{
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, e);
}
}}
}
public void produce(int i) throws InterruptedException
{
while(queue.size() == size)
{
synchronized(queue)
{
System.out.println("Queue is full "+Thread.currentThread().getName() +" is waiting, size: "+queue.size());
queue.wait();
}
}
synchronized(queue)
{
queue.add(i);
queue.notifyAll();
}
}
}
class Consumer extends Thread
{
private final ArrayList<Integer> queue;
private final int size;
public Consumer(ArrayList<Integer> queue, int size)
{
this.queue = queue;
this.size = size;
}
public void run()
{
while(true)
{
try
{ System.out.println("Consumed: "+consume());
Thread.sleep(1000);
}
catch(Exception e)
{
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, e);
}
}
}
public int consume() throws InterruptedException
{
while(queue.isEmpty())
{
synchronized(queue)
{
System.out.println("Queue is empty "+Thread.currentThread().getName()+" is waiting, size: "+queue.size());
queue.wait();
}
}
synchronized (queue)
{
queue.notifyAll();
System.out.println("Consumed by id "+Thread.currentThread().getId());
return (Integer) queue.remove(0);
}
}
}
How can I carry out the above steps?
I’m supposed to assign a unique number to each producer and consumer
thread. How do I assign a unique number to producer and consumer
threads?
Add an instance (non-static) variable to the Producer/Consumer classes. When you initialize the new Producer/Consumer Objects, pass in the unique number. You can keep track of what number you're on with an int counter in your main class.
2) The producer thread operates in an infinite loop. It produces a
data item (a string) with the following format: < producer number >_<
data item number > . For example the 1st data item from thread number
1 will be 1_1 and second data item from thread number 3 will be 3_2.
How do create data items in such a format?
Use synchronized methods and/or atomic variables. Look into Java Concurrency.
3) Then the Producer thread writes an entry into the producer log file
(< producer number > “Generated” < data item >). Upon writing the log
entry, it attempts to insert into the buffer. If insertion is
successful, it creates an entry into the log file (< producer number >
< data item > “Insertion successful”). How do I write such a code?
My answer is the same as the previous question: read about Java concurrency. Spend an hour reading about synchronization, locks, and atomic variables and I guarantee you will easily write your program.
For producer consumer problem best solution is BlockingQueue. I was testing a few things so designed same kind of program now modified it as per your need.
See if it helps.
import java.util.concurrent.*;
public class ThreadingExample {
public static void main(String args[]){
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<Message>(100);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Producer(blockingQueue));
exec.execute(new Consumer(blockingQueue));
}
}
class Message{
private static int count=0;
int messageId;
Message(){
this.messageId=count++;
System.out.print("message Id"+messageId+" Created ");
}
}
class Producer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Producer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Producer Started");
try {
blockingQueue.put(new Message());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer Done");
}
}
}
class Consumer implements Runnable{
private BlockingQueue<Message> blockingQueue;
Consumer(BlockingQueue<Message> blockingQueue){
this.blockingQueue=blockingQueue;
}
#Override
public void run(){
while(!Thread.interrupted()){
System.out.print("Concumer Started");
try{
Message message = blockingQueue.take();
System.out.print("message Id"+message.messageId+" Consumed ");
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Concumer Done");
}
}
}
I tried the following which might work for you, except for the buffer condition on 3, which you can add the part of the code by yourself.
Hope this helps.
public class Message {
private String msg;
public Message(String msg) {
super();
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
private BlockingQueue<Message> queue;
private boolean run = true;
public Producer(BlockingQueue<Message> queue) {
super();
this.queue = queue;
}
public void setRun(boolean val) {
this.run = val;
}
#Override
public void run() {
int i = 0;
while (run) {
Message msg = new Message(Thread.currentThread().getName() + "_"+ i);
try {
Thread.sleep(i * 100);
queue.put(msg);
System.out.println("Producer: "+Thread.currentThread().getName()+" produced and added to the queue: "+msg.getMsg());
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
if(i==10){
setRun(false);
System.out.println(Thread.currentThread().getName()+" stopped");
}
}
}
}
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable{
private BlockingQueue<Message> queue;
private boolean run = true;
public Consumer(BlockingQueue<Message> queue) {
super();
this.queue = queue;
}
public void setRun(boolean val){
this.run = val;
}
#Override
public void run() {
while(run){
try {
Thread.sleep(100);
Message msg = queue.take();
System.out.println("Consumer: "+Thread.currentThread().getName()+" generated/consumed "+msg.getMsg());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerMain {
public static void main(String[] args) {
System.out
.println("please enter the number of producer:consumer:size of the queue in order");
Scanner scan = new Scanner(System.in);
Thread[] prodThreads = new Thread[scan.nextInt()];
Thread[] consThreads = new Thread[scan.nextInt()];
BlockingQueue<Message> queue = new ArrayBlockingQueue<Message>(scan.nextInt());
for (int i = 0; i < prodThreads.length; i++) {
prodThreads[i] = new Thread(new Producer(queue), "" + i);
prodThreads[i].start();
}
for (int i = 0; i < consThreads.length; i++) {
consThreads[i] = new Thread(new Consumer(queue), "" + i);
consThreads[i].start();
}
}
}
Please refer the below code. You can change the constant values based on the command line arguments. I have tested the code, its working as per your requirement.
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumerProblem {
public static int CAPACITY = 10; // At a time maximum of 10 tasks can be
// produced.
public static int PRODUCERS = 2;
public static int CONSUMERS = 4;
public static void main(String args[]) {
Queue<String> mTasks = new LinkedList<String>();
for (int i = 1; i <= PRODUCERS; i++) {
Thread producer = new Thread(new Producer(mTasks));
producer.setName("Producer " + i);
producer.start();
}
for (int i = 1; i <= CONSUMERS; i++) {
Thread consumer = new Thread(new Consumer(mTasks));
consumer.setName("Consumer " + i);
consumer.start();
}
}
}
class Producer implements Runnable {
Queue<String> mSharedTasks;
int taskCount = 1;
public Producer(Queue<String> mSharedTasks) {
super();
this.mSharedTasks = mSharedTasks;
}
#Override
public void run() {
while (true) {
synchronized (mSharedTasks) {
try {
if (mSharedTasks.size() == ProducerConsumerProblem.CAPACITY) {
System.out.println("Producer Waiting!!");
mSharedTasks.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (mSharedTasks.size() != ProducerConsumerProblem.CAPACITY) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
String produceHere = Thread.currentThread().getName()
+ "_Item number_" + taskCount++;
synchronized (mSharedTasks) {
mSharedTasks.add(produceHere);
System.out.println(produceHere);
if (mSharedTasks.size() == 1) {
mSharedTasks.notifyAll(); // Informs consumer that there
// is something to consume.
}
}
}
}
}
}
class Consumer implements Runnable {
Queue<String> mSharedTasks;
public Consumer(Queue<String> mSharedTasks) {
super();
this.mSharedTasks = mSharedTasks;
}
#Override
public void run() {
while (true) {
synchronized (mSharedTasks) {
if (mSharedTasks.isEmpty()) { // Checks whether there is no task
// to consume.
try {
mSharedTasks.wait(); // Waits for producer to produce!
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
while (!mSharedTasks.isEmpty()) { // Consumes till task list is
// empty
try {
// Consumer consumes late hence producer has to wait...!
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (mSharedTasks) {
System.out.println(Thread.currentThread().getName()
+ " consumed " + mSharedTasks.poll());
if (mSharedTasks.size() == ProducerConsumerProblem.CAPACITY - 1)
mSharedTasks.notifyAll();
}
}
}
}
}
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("Consumer #"
+ this.number
+ " got: " + value);
}
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("Producer #" + this.number
+ " put: " + i);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}

How to handle wait() notify()?

Here I have two run methods which should synchronize each other.
Poller Class:
*/
public void run() {
int seqId = 0;
while(true) {
List<KpiMessage> list = null;
try{
if(!accumulator.isUsed){
try {
list = fullPoll(seqId);
if (!list.isEmpty()) {
seqId = list.get(0).getSequence();
accumulator.manageIngoing(list);
}
System.out.println("Updated");
wait();
} catch (Exception e1) {
e1.printStackTrace();
}
}
} catch (Exception e){
// TODO:
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
/**
* Method which defines polling of the database and also count the number of Queries
* #param lastSeq
* #return pojo col
* #throws Exception
*/
public List<KpiMessage> fullPoll(int lastSeq) throws Exception {
Statement st = dbConnection.createStatement();
System.out.println("Polling");
ResultSet rs = st.executeQuery("Select * from msg_new_to_bde where ACTION = 814 and
STATUS = 200 order by SEQ DESC");
List<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
try {
while (rs.next()) {
KpiMessage filedClass = convertRecordsetToPojo(rs);
pojoCol.add(filedClass);
}
for (KpiMessage pojoClass : pojoCol) {
System.out.print(" " + pojoClass.getSequence());
System.out.print(" " + pojoClass.getTableName());
System.out.print(" " + pojoClass.getAction());
System.out.print(" " + pojoClass.getKeyInfo1());
System.out.print(" " + pojoClass.getKeyInfo2());
System.out.print(" "+ pojoClass.getStatus());
System.out.println(" " + pojoClass.getEntryTime());
}
} finally {
try {
st.close();
rs.close();
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
Processing and Updating Class:
public void run() {
while(true){
try {
while(!accumulator.isUsed)
{
try {
System.out.println("Waiting for new outgoingmessages");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Collection<KpiMessage> outgoingQueue = generate(accumulator.outgoingQueue);
accumulator.manageOutgoing(outgoingQueue, dbConnection);
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
}
I have a logical error:
The poller is polling not only for new messsage but also reads the DB again and again from the first.
Also Updates again and again.
How to solve this synchronization problem.
Alternatively you could use a BlockingQueue to transfer the data between threads.
See BlockingQueue for details.
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i++);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if ( i != null ) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue queue = new LinkedBlockingQueue();
Producer p = new Producer(queue);
Consumer c = new Consumer(queue);
Thread pt = new Thread(p);
Thread ct = new Thread(c);
// Start it all going.
pt.start();
ct.start();
// Close it down
pt.join();
ct.join();
}
You should synchronize or rather hold the lock or monitor for the object that you are calling wait() or notify() on.
Here is what will help you : wait() throwing IllegalArgumentException
synchronized(lockObject){
lockObject.wait(); //you should hold the lock to be able to call wait()
}

Categories

Resources