I have implemented the classic producer/consumer problem, using a shared buffer class.
For some reason I am not getting the correct sequence of outputs.
I have tried so many times, but could not spot the flaw, can someone please point out the mistake?
public class BufferProdCons {
boolean produced = false;
int data;
public synchronized void produceData(int d) {
while (produced) {
try {
wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
// System.out.println("data produced");
data = d;
produced = true;
this.notify();
}
public synchronized int consumeData() {
while (!produced) {
try {
wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
// System.out.println("data consumed");
int d =data;
produced = false;
this.notify();
return d;
}
}
public class Consumer extends Thread {
BufferProdCons buffer ;
Consumer(BufferProdCons buf){
buffer = buf;
}
public void run(){
for (int i =0;i<10;i++){
int d=buffer.consumeData();
System.out.println("Consumed data "+d);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Producer extends Thread {
BufferProdCons buffer;
Producer(BufferProdCons buf){
buffer = buf;
}
#Override
public void run(){
for(int i=0;i<10;i++){
System.out.println("Produced "+i);
buffer.produceData(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MainProdCons {
public static void main(String[] args) {
BufferProdCons buffer = new BufferProdCons();
Thread t1 = new Producer(buffer);
Thread t2 = new Consumer(buffer);
t1.start();t2.start();
}
}
sample Output
Produced 0
Consumed data 0
Produced 1
Consumed data 1
Produced 2
Produced 3
Consumed data 2
Produced 4
Consumed data 3
Produced 5
Consumed data 4
Produced 6
Consumed data 5
Produced 7
Consumed data 6
Produced 8
Consumed data 7
Produced 9
Consumed data 8
Consumed data 9
My understanding is that , the sequence of producer and consumer lines should be alternate, But as you can see sometimes they appear in succession.
Related
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();
}
}
I'm trying to make a parking lot program. I've got multiple threads that put car objects into a queue, then into a shared buffer. Once the sharedBuffer reaches the maximum of 50 elements.
Here is the problem: Once the shared Buffer reaches the maximum amount of elements. I want the thread to start queuing up elements to the queue. Instead the thread waits for the semaphore to open a spot.
public class Buffer {
private LinkedList queue = new LinkedList();
private Semaphore spots = new Semaphore(50);
public synchronized void put(String car) {
try {
spots.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
queue.addLast(car);
notifyAll();
}
public synchronized String get() throws InterruptedException {
String t = (String) queue.removeFirst();
spots.release();
notifyAll();
return t;
}
public int getSize() {
return queue.size();
}
}
Method in my Queue class that either adds the car to the buffer or adds it straight to the queue if the buffer is full.
public void addToQueue(int queue) {
if (queue == 1 && northQueue<20) {
if(buffer.getSize()==50){
northQueue++;
}else{
buffer.put("Volvo");
}
}
}
public void run() {
while (true) {
// System.out.println("Thread: " + threadNumber);
eq.addToQueue(threadNumber);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
I want to be able to print Fibonacci series using threads, so I'm creating 2 threads:
A producer which will fill the array according to the formula f(n) = f(n-1)+f(n-2)
A consumer that will print the elements that has been calculated so far
I will set the shared array to be able to store only 5 elements at time, and the consumer will free up space in the array, allowing the producer to add more elements.
This is my consumer code:
public class Consumer implements Runnable
{
private LinkedList<Integer> sharedArray;
public Consumer(LinkedList<Integer> array, int size, int series)
{
sharedArray = array;
}
#Override
public void run()
{
while (true)
{
try
{
print();
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void print() throws InterruptedException
{
while (true)
{
synchronized (sharedArray)
{
while (sharedArray.isEmpty())
{
try
{
sharedArray.wait();
} catch (Exception ex)
{
ex.printStackTrace();
}
}
System.out.print(sharedArray.get(0) + " ");
sharedArray.notifyAll();
}
}
}
}
And this is the producer code:
public class Producer implements Runnable
{
private LinkedList<Integer> sharedArray;
private int sharedArraySize;
private int seriesSize;
public Producer(LinkedList<Integer> array, int size, int series)
{
sharedArray = array;
sharedArraySize = size;
seriesSize = series;
}
#Override
public void run()
{
for (int i = 0; i < seriesSize; i++)
{
try
{
calculate(i);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void calculate(int n) throws InterruptedException
{
synchronized (sharedArray)
{
while (sharedArray.size() == sharedArraySize)
{
sharedArray.wait();
}
if (n == 0 || n == 1)
{
sharedArray.add(n, 1);
} else
{
sharedArray.add(n, sharedArray.get(n - 1) + sharedArray.get(n - 2));
}
sharedArray.notifyAll();
}
}
}
and the main class that starts both of the threads:
public class FibThreads
{
public static void main(String[] args)
{
int seriesSize = 18; //Integer.parseInt(args[0]);
int elementsInLine = 0;//Integer.parseInt(args[1]);
int sharedArraySize = 5;//Integer.parseInt(args[2]);
LinkedList<Integer> sharedArray = new LinkedList<Integer>();
Thread producer = new Thread(new Producer(sharedArray,sharedArraySize,seriesSize), "Producer");
Thread consumer = new Thread(new Consumer(sharedArray,sharedArraySize,seriesSize), "Consumer");
producer.start();
consumer.start();
System.out.println("End of main");
}
}
My problem is: After trying to run this, I get an infinite loop, because as soon as there is a new item in the array, the consumer takes it and free up space, which means the array can't really be filled with items because the consumer frees it immediately.
How can I make it work?
Your new problem with the only "1" output is because .get() does the same like peekFirst you get the first element but it does not remove it!
What I assume you want is System.out.print(sharedArray.pollFirst() + " "); which retrives the first element and removes it from the linked list.
Your Error was probably because you removed a node but you did not updated n in your producer which then pointed to the wrong index as it should be -1 for every removed element.
EDIT: Something you should also check is that your consumer does not remove all elements as you need at least 2 to calculate the next fibonacci number!
EDIT 2: something like
while (sharedArray.isEmpty()||sharedArray.size()<=2)
{
try
{
sharedArray.wait();
} catch (Exception ex)
{
ex.printStackTrace();
}
}...
And you need update N in your producer, you could change it to sharedArray.add(sharedArray.size(),sharedArray.size()-1+sharedArray.size()-2); so you would never go out of bounderys.
You can do this because you already check beforehand if you reached the limitation and n isn't needed at all.
EDIT 3:
sharedArray.add(sharedArray.size(),sharedArray.size()-1+sharedArray.size()-2);
should be
sharedArray.add(sharedArray.size(),sharedArray.get(sharedArray.size()-1)+sharedArray.get(sharedArray.size()-2));
My bad should have mentioned that....
What would be a JUnit based code to run this 3 methods each as 10 concurrent threads.
#RunWith(SpringJUnit4ClassRunner.class
#SpringBootTest
public class TestClass {
#Test
public void readFromDBOneRecord(){
try {
dbService.findOneByID("1");
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
#Test
public void writeToDBOneRecord(){
try {
dbService.save(entity.builder()
.setID("1").setName("John").build())
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
#Test
public void deleteDbRecord(){
try {
dbService.delete("1");
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
}
In some cases some of the methods would throw exceptions. Like if the delete being executed before writeToDBOneRecord.
So the sequence would be say for only 3 threads per method e.g.:
OperationNr|| OperationName || [ThreadNr/total threads per method]OperationType
1. write [2/3]w
2. read [1/3]r
3. read [3/3]r
4. delete [2/3]d
5. read [2/3]r
6. delete [3/3]d ->exception no record
7. write [1/3]w
8. write [3/3]w ->exception record already present
9. delete [1/3]d
What would the code for executing this 3 test methods each in 10 concurrent threads (30 in total)?
As you want to do everything in parallel, I would mix everything and rely on CountDownLatch instances to synchronize the threads as next:
#Test
public void testMultiThreading() throws Exception {
// Total of reader threads
int reader = 5;
// Total of writer threads
int writer = 3;
// Total of remover threads
int remover = 1;
// CountDownLatch used to release all the threads at the same time
final CountDownLatch startSignal = new CountDownLatch(1);
// CountDownLatch used to be notified when all threads did their task
final CountDownLatch doneSignal = new CountDownLatch(reader + writer + remover);
// List in which we collect all the errors
final List<Exception> errors = Collections.synchronizedList(new ArrayList<>());
// Create all the reader threads and start them
for (int i = 0; i < reader; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.findOneByID("1");
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Create all the writer threads and start them
for (int i = 0; i < writer; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.save(entity.builder()
.setID("1").setName("John").build());
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Create all the remover threads and start them
for (int i = 0; i < remover; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.delete("1");
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Release the threads
startSignal.countDown();
// Wait until all threads did their task
doneSignal.await();
// If an error has been collected, print the stack trace and throws the
// first error to make the test fail
if (!errors.isEmpty()) {
for (Exception e : errors) {
e.printStackTrace();
}
throw errors.get(0);
}
}
NB: If you want a given unit test to be executed by several concurrent threads, have a look to contiperf but it won't allow you to mix them as you want to achieve
This my code ,the code run the end is not my excepted.
I think the PriorityBlockingQueue sorted by Priority but the end is not my expected,Who can told me why.
public class TestPriorityQueue {
static Random r=new Random(47);
public static void main(String args[]) throws InterruptedException{
final PriorityBlockingQueue q=new PriorityBlockingQueue();
ExecutorService se=Executors.newCachedThreadPool();
//execute producer
se.execute(new Runnable(){
public void run() {
int i=0;
while(true){
q.put(new PriorityEntity(r.nextInt(10),i++));
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//execute consumer
se.execute(new Runnable(){
public void run() {
while(true){
try {
System.out.println("take== "+q.take()+" left:== ["+q.toString()+"]");
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("shutdown");
}
}
class PriorityEntity implements Comparable<PriorityEntity> {
private static int count=0;
private int id=count++;
private int priority;
private int index=0;
public PriorityEntity(int priority,int index) {
this.priority = priority;
this.index=index;
}
public String toString(){
return id+"* [index="+index+" priority="+priority+"]";
}
//数字大,优先级高
public int compareTo(PriorityEntity o) {
return this.priority < o.priority ? 1
: this.priority > o.priority ? -1 : 0;
}
}
The following are the results,I would be very grateful to you for your help
Some observations:
in most cases the size of your queue was 1. Clearly, no sort order is relevant in any of those.
In a few cases the queue size may have been two, and in no such case does the output insinuate that an element of lower priority was preferred. I stress the verb "insinuate" because...
your code has no synchronized blocks so nothing prevents the following sequence of operations:
q.take(); // consumer thread
q.put(); // producer thread
q.toString(); // consumer thread
with the legitimate outcome of q.toString() showing an element of higher priority than was taken.