buffer getting fully filled before consuming - java

import java.awt.List;
import java.util.ArrayList;
import java.util.Random;enter code here
public class shared {
private int [] buffer;
private int capacity;
Object lock;//=new Object();
int count=0;
int i,j;
//int i=0,j=0;
public shared(int capacity){
this.capacity = capacity;
buffer = new int[capacity];
i=0;
j=0;
lock = new Object();
//for(int k=0;k<capacity;k++){
//buffer[k]=0;
//}
}
public void producer() throws InterruptedException {
//synchronized(lock){
while(true){
synchronized(lock){
Random rn = new Random();
int number = rn.nextInt(100);
Thread.sleep(1000);
while(count==capacity){
try{
System.out.println("BUffer is full");
lock.wait();
}catch(InterruptedException e){
}
//System.out.println("buffer is full");
}
System.out.println("producing" + number);
buffer[i] = number;
i = (i+1)%capacity;
count++;
lock.notifyAll();
}
}
}
public void consumer(){
//synchronized(lock){
while(true){
synchronized(lock){
while(count==0){
try{
lock.wait();
}catch(InterruptedException e){
}
}
//int a = buffer.get(0);
//buffer.remove(0);
int consumed = buffer[j];
System.out.println("consuming" + consumed);
j=(j+1)%capacity;
count--;
lock.notifyAll();
if((consumed%2)==0){
System.out.println("the number displayed by the consumer is " + consumed);
}
}
}
}
}
public class producer implements Runnable {
shared h;
public producer(shared s) {
// TODO Auto-generated constructor stub
h=s;
}
public void run(){
//for(int i=0;i<10;i++){
try {
h.producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class consumer implements Runnable {
shared h;
public consumer(shared s) {
// TODO Auto-generated constructor stub
h=s;
}
public void run(){
//for(int i=0;i<5;i++){
h.consumer();
}
}
public class implement {
public static void main(String [] args) throws InterruptedException{
shared s = new shared(10);
Thread pro1 = new Thread(new producer(s));
Thread con1 = new Thread(new consumer(s));
pro1.start();
con1.start();
pro1.join();
con1.join();
}
}
This is the entire code that I have written. The problem that I am getting is that my buffer is getting entirely full first then it is getting consumed. I want it to be consumed randomly i.e. when the first element fills up it might get get consumed or after 3-4 elements filled up.

I've reproduced your experiment and checked that, in fact, the producer thread fills the buffer before the consumer comes in. And that's because only when the buffer is full, the producer calls wait to give the consumers a chance.
The behaviour in a multi-threaded environment is always something random. Surely when the execution exits from the producer's synchronized block, the next iteration comes so quickly that it enters again in the block before other threads have a chance to.
If you want to produce and consume with an random ratio, I suggest you other means:
First, move the sleep out of the synchronized block.
Or else, do always a wait first-notify last into your producer loop, but performing a random number of inserts between them.

Related

Why Lock is not pass to another thread

When buffer queue is empty Thread is waiting for Another thread to enter element in buffer queue after it notifies the first thread to activate and run the remaining code but only one thread which is taking input in buffer queue is active and another thread is not working. I think thread notify is not working.
Main.java
public class Main {
public static void main(String[] args) throws InterruptedException {
LRUManager lruManager = new LRUManager();
Thread input = new Thread(lruManager);
Thread lruCache = new Thread(lruManager);
input.setName("Input");
lruCache.setName("LRUCache");
input.start();
lruCache.start();
}
}
LRUManager.java
public class LRUManager implements Runnable {
LRUCache lruCache = new LRUCache();
Input input = new Input();
#Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("ThreadName:" + threadName);
if (threadName.equalsIgnoreCase("Input")) {
inputController();
} else if (threadName.equalsIgnoreCase("LRUCache")) {
lruController();
}
}
synchronized private void lruController() {
if (input.checkbufferQueue()) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
int page = input.getinput();
lruCache.addPage(page);
lruCache.display();
run();
}
}
synchronized private void inputController() {
input.takeInput();
input.printQueue();
notifyAll();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
run();
}
}
Input.java
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Input {
Scanner scanner = new Scanner(System.in);
int page;
Queue<Integer> bufferQueue = new LinkedList<Integer>();
void takeInput() {
System.out.println("Please enter Page in the cache");
page = scanner.nextInt();
bufferQueue.add(page);
}
int getinput() {
int page = bufferQueue.poll();
return page;
}
boolean checkbufferQueue()
{
return bufferQueue.isEmpty();
}
void printQueue() {
System.out.print("bufferQueue: ");
for(int page: bufferQueue) {
System.out.print(page+" ");
}
System.out.println("\n");
}
}
LRUCache.java
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
public class LRUCache {
static Deque<Integer> cache = new LinkedList<Integer>();
Input input = new Input();
private int cacheSize = 4;
int page;
void addPage(int page) {
if (!cache.contains(page)) {
if (cache.size() == cacheSize) {
cache.removeLast();
}
} else {
cache.remove(page);
}
cache.push(page);
}
public void display() {
Iterator<Integer> itr = cache.iterator();
while (itr.hasNext()) {
System.out.print(itr.next() + " ");
}
System.out.print("\n");
}
}
output
ThreadName:LRUCache
ThreadName:Input
Please enter Page in the cache
1
bufferQueue: 1
ThreadName:Input
Please enter Page in the cache
2
bufferQueue: 1 2
ThreadName:Input
Please enter Page in the cache
3
bufferQueue: 1 2 3
ThreadName:Input
Please enter Page in the cache
4
bufferQueue: 1 2 3 4
ThreadName:Input
Please enter Page in the cache
5
bufferQueue: 1 2 3 4 5
ThreadName:Input
Please enter Page in the cache
Your input thread is never exiting method synchronization, hence never releasing the lock. Notify tells the LRU thread to move out of waiting state, but it then the thread is then left blocked waiting for the lock that never arrives.
What you need is a wait() after the notifyAll() in inputController(), and a notifyAll() before wait in the lruController().
Refer to https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html for examples.
Also make the recursive call from lruController() outside the else block.
Could you also change the recursive calls within the thread to call inputController() or lruController() instead of run directly.

Java semaphore for parking lot

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) {
}
}
}

trying to print a Fibonacci series using producer and consumer pattern

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....

Threading in Sequence

I am trying to learn how to write a program which performs a given set of tasks in sequence with the help of threads. For example, Writing a program which have 3 different threads print 1111…, 22222…., 333333……, so that the output will be 1,2,3,1,2,3,1,2,3…..? OR for e.g. 2 threads one is printing odd numbers and other even numbers, but the output should be printed in sequence - i.e. one even and then odd.
I would like to learn how to write similar kind of programs in which different threads print different stuff concurrently and the output should be printed in sequence.
What is the basic concept in writing these programs. Can we use ThreadPools/Executors for the purpose ? For e.g. can we use
ExecutorService exectorService = Executors.newFixedThreadPool(3);
Can we use Future, FurtureTask, Callable, execute, submit ...? I know these concepts but I am not able to connect the dots for solving the above scenarios.
Please guide me how to go about writing these kind of programs using multithreading / concurrency.
I have written a program using wait()/notifyAll(). Following is the program. I am not executing the consumer as I am printing the whole sequence at the end. Also I am limiting the capacity of the queue to be 15. So I am basically printing the odd / even range till 15.
public class ProduceEven implements Runnable {
private final List<Integer> taskQueue;
private final int MAX_CAPACITY;
public ProduceEven (List<Integer> sharedQueue, int size) {
this.taskQueue = sharedQueue;
this.MAX_CAPACITY = size;
}
#Override
public void run() {
// TODO Auto-generated method stub
int counter = 0;
while (counter < 15) {
try {
produce(counter++);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
private void produce (int i) throws InterruptedException {
synchronized (taskQueue) {
while (taskQueue.size() == MAX_CAPACITY) {
System.out.println("Queue is full : "+Thread.currentThread().getName()+" is waiting , size: "+ taskQueue.size());
taskQueue.wait();
}
Thread.sleep(1000);
if(i%2==0) {
taskQueue.add(i);
}
taskQueue.notifyAll();
}
}
}
public class ProduceOdd implements Runnable {
private final List<Integer> taskQueue;
private final int MAX_CAPACITY;
public ProduceOdd (List<Integer> sharedQueue, int size) {
this.taskQueue = sharedQueue;
this.MAX_CAPACITY = size;
}
#Override
public void run() {
int counter = 0;
while (counter < 15) {
try {
produce(counter++);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
private void produce (int i) throws InterruptedException {
synchronized (taskQueue) {
while (taskQueue.size() == MAX_CAPACITY) {
System.out.println("Queue is full : "+Thread.currentThread().getName()+" is waiting , size: "+ taskQueue.size());
taskQueue.wait();
}
Thread.sleep(1000);
if(i%2==1) {
taskQueue.add(i);
}
taskQueue.notify();
}
}
}
public class OddEvenExampleWithWaitAndNotify {
public static void main(String[] args) {
List<Integer> taskQueue = new ArrayList<Integer>();
int MAX_CAPACITY = 15;
Thread tProducerEven = new Thread(new ProduceEven(taskQueue, MAX_CAPACITY), "Producer Even");
Thread tProducerOdd = new Thread(new ProduceOdd(taskQueue, MAX_CAPACITY), "Producer Odd");
tProducerEven.start();
tProducerOdd.start();
try {
tProducerEven.join();
tProducerOdd.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
ListIterator listIterator = taskQueue.listIterator();
System.out.println("Elements Are:: ");
while(listIterator.hasNext()) {
System.out.print(listIterator.next()+" ");
}
}
}
The output which I get is: Elements Are:: 02134657911810131214
The output is all jumbled up. Why is it not in sequence. 01234567891011121314 What am I missing. I would be now trying to make the program using Semaphores. Also how do we make this program using explicit locks?
Yes, you can use ExecutorService as a starting point to run your threads. You can also create and start your Threads manually, that would make no difference.
The important thing is that your Threads will run in parallel if you do not synchronize them (i.e., they have to wait for one another). To synchronize you can, e.g. use Semaphores or other thread communication mechanisms.
You wrote in the comments you have written a producer/consumer program. It's a bit of the same thing. Each time the 1-Thread produces a 1, the 2-Thread must know that it can now produce a 2. When it is finished, it must let the 3-Thread know that it must produce a 3. The basic concepts are the same. Just the threads have both producer and consumer roles.
Hi this is one sample program to print Odd and Even using two thread and using thread synchronization among them.
Also we have used Executor framework which is not mandatory, you can create thread using new Thread() as well. For quick prototype I have used system.exit() which can be replaced with graceful shutdown of threads like, interruption and all.
package com.ones.twos.threes;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class OnesTwos {
public static void main(String[] args) {
BlockingQueue<Integer> bq1 = new ArrayBlockingQueue<Integer>(100);
BlockingQueue<Integer> bq2 = new ArrayBlockingQueue<Integer>(100);
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
bq1.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.submit(new OddEven(bq1, bq2));
executorService.submit(new OddEven(bq2, bq1));
executorService.shutdown();
}
public static class OddEven implements Runnable {
BlockingQueue<Integer> bq1;
BlockingQueue<Integer> bq2;
public OddEven(BlockingQueue<Integer> bq1, BlockingQueue<Integer> bq2) {
this.bq1 = bq1;
this.bq2 = bq2;
}
#Override
public void run() {
while (true) {
try {
int take = bq1.take();
System.out.println(take);
bq2.offer(take + 1);
if (take > 20)
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Mycode is also similar to Anirban's, except I am not using executor framework,
public class TestThread {
public static void main(String[] args) {
Boolean bol = new Boolean(true);
(new Thread(new Odd(bol), "odd")).start();
(new Thread(new Even(bol), "even")).start();
}
}
public class Even implements Runnable {
private Boolean flag;
public Even(Boolean b) {
this.flag = b;
}
#Override
public void run() {
for (int i = 2; i < 20; i = i + 2) {
synchronized (flag) {
try {
System.out.println(Thread.currentThread().getName()+":"+i);
Thread.sleep(1000);
flag.notify();
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Odd implements Runnable {
private Boolean flag;
public Odd(Boolean b) {
this.flag = b;
}
#Override
public void run() {
for (int i = 1; i < 20; i = i + 2) {
synchronized (flag) {
try {
System.out.println(Thread.currentThread().getName()+":"+i);
Thread.sleep(1000);
flag.notify();
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
By establishing the thread pool of 3 (ExecutorService exectorService = Executors.newFixedThreadPool(3); you are essentilly limiting the executor capacity to 3 and other incoming threads will be on hold. If you want to run them in paralel you can just submit them at once. If you want to wait for each other and want to find out the result I suggest you use Callable. Personally I really like Callable because after submiting it you can just call the get method of Future, wait for a returned value from the executed thread and then continue to the next one. From the API you can see this:
/**
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
* Future's {#code get} method will return the task's result upon
* successful completion.
*
*
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
* {#code result = exec.submit(aCallable).get();}
And a very good example here. If you go for the Callable alternative then you don't need a Thread pool. Just a normal executor is fine. Remember to shut the executor down in the end.
class MyNumber {
int i = 1;
}
class Task implements Runnable {
MyNumber myNumber;
int id;
Task(int id, MyNumber myNumber) {
this.id = id;
this.myNumber = myNumber;
}
#Override
public void run() {
while (true) {
synchronized (myNumber) {
while (myNumber.i != id) {
try {
myNumber.wait(); //Wait until Thread with correct next number
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(id);
if (myNumber.i == 1) {
myNumber.i = 2;
} else if (myNumber.i == 2) {
myNumber.i = 3;
} else {
myNumber.i = 1;
}
myNumber.notifyAll();
}
}
}
}
In main method:
MyNumber myNumber = new MyNumber();
new Thread(new Task(1, myNumber)).start();
new Thread(new Task(2, myNumber)).start();
new Thread(new Task(3, myNumber)).start();
Hi here we have used 2 thread one to print even and another to print odd.
Both are separate and have no relation to each other.
But we have to do a synchronization mechanism between them. Also we need a mechanism to let the ball rolling, i.e. start one thread printing.
Each thread is waiting on condition and after doing it's task it lets other thread work and put ownself in waiting state.
Well happy path works fine, but we need special care when even thread is not in waiting state and the signal() from main fires, in that case even thread will never able to wake up and the program hangs.
So to make sure main thread successfully sends a signal() to even thread and even thread does not miss that we have used Phaser(with party) and checking even thread state in while loop in main.
Code is as below.
package com.ones.twos.threes;
import java.util.concurrent.Phaser;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class OnesTwosTrial2 {
public static void main(String[] args) {
Lock lk = new ReentrantLock();
Phaser ph = new Phaser(3); // to let main start the even thread
Condition even = lk.newCondition();
Condition odd = lk.newCondition();
OnesTwosTrial2 onestwostrial2 = new OnesTwosTrial2();
Thread ev = onestwostrial2.new Evens(lk, even, odd, ph);
Thread od = onestwostrial2.new Odds(lk, even, odd, ph);
ev.start();
od.start();
System.out.println("in main before arrive");
ph.arriveAndAwaitAdvance();
System.out.println("in main after arrive");
// we have to make sure odd and even thread is
// started and waiting on respective condition.
// So we used Phaser with 3, because we are having here
// 3 parties (threads)
// main, odd,even. We will signal only when all the
// threads have started.
// and waiting on conditions.
while (!Thread.State.WAITING.equals(ev.getState())) {
System.out.println("waiting");
}
lk.lock();
even.signal();
lk.unlock();
}
class Evens extends Thread {
Lock lk;
Condition even;
Condition odd;
Phaser ph;
public Evens(Lock lk, Condition even, Condition odd, Phaser ph) {
this.lk = lk;
this.even = even;
this.odd = odd;
this.ph = ph;
}
#Override
public void run() {
System.out.println("even ph");
int cnt = 0;
while (cnt < 20) {
try {
lk.lock();
ph.arrive();
even.await();
System.out.println(cnt);
cnt += 2;
odd.signal();
lk.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Odds extends Thread {
Lock lk;
Condition even;
Condition odd;
Phaser ph;
public Odds(Lock lk, Condition even, Condition odd, Phaser ph) {
this.lk = lk;
this.even = even;
this.odd = odd;
this.ph = ph;
}
#Override
public void run() {
System.out.println("odd ph");
int cnt = 1;
while (cnt < 20) {
try {
lk.lock();
ph.arrive();
odd.await();
System.out.println(cnt);
cnt += 2;
even.signal();
lk.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

adding multiple values in synchronized buffer

So I have a Producer, Consumer and a shared Synchronized buffer.
The producer creates a number (that gets saved in the buffer)
And the consumer gets 5 guesses to guess the number.
Once the consumer guesses correctly it’s asked whether it wants to play again and number of times guessed correctly is saved in the buffer.
My synchronizedBuffer class is all wrong. I don't even know where to begin to implement the second value into it. Even a little hint as to how I'm supposed to do it will be much appreciated. I'm not allowed to use array-blocking queues.
//Class: Producer
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class Producer implements Runnable {
private final static Random generator = new Random();
private final Buffer sharedLocation;
public Producer(Buffer shared) {
sharedLocation = shared;
}
public void run() {
try {
int x = ThreadLocalRandom.current().nextInt(1, 10);
Thread.sleep(generator.nextInt(3000)); // random sleep
sharedLocation.set(x); // set value in buffer
System.out.printf("\n", x);
}
catch (InterruptedException exception) {
exception.printStackTrace();
}
System.out.println("Producer done producing");
}
}
//Class: Consumer
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class Consumer implements Runnable {
private final static Random generator = new Random();
private final Buffer sharedLocation;
public Consumer(Buffer shared) {
sharedLocation = shared;
}
public void run() {
int correct = 0;
outerloop: for (int i = 1; i <= 5; i++) {
try {
int x = ThreadLocalRandom.current().nextInt(1, 10);
Thread.sleep(generator.nextInt(2000));
if (x == sharedLocation.get()) {
System.out.println(x);
System.out.println("correct guess was " + x);
correct++;
sharedLocation.set(correct);
break outerloop;
}
System.out.print(x + "\n");
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
}
}
public class SynchronizedBuffer implements Buffer {
private int buffer = -1;
private boolean occupied = false;
public synchronized void set(int value) throws InterruptedException {
while (occupied) {
System.out.println("Producer tries to write.");
System.out.println("Consumer tries to guess");
wait();
} // end while
buffer = value;
occupied = true;
displayState("Producer writes " + buffer);
notifyAll();
buffer = value;
}
public synchronized int get() throws InterruptedException {
while (!occupied) {
System.out.println("Consumer tries to guess.");
displayState("Buffer empty. Consumer waits.");
wait();
}
occupied = false;
notifyAll();
return buffer;
}
public void displayState(String operation) {
System.out.printf("%-40s%d\t\t%b\n", operation, buffer, occupied);
}
}

Categories

Resources