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) {
}
}
}
Related
I've been trying to make a simple implementation of Thread-Pool using Active Objects.
Here is my Main:
public static void main(String[] args){
MyThreadPool tp = new MyThreadPool(100,3);
tp.execute(()->{
try { Thread.sleep(5*1000); } catch (InterruptedException e) {}
System.out.println("42");
});
tp.shutDown();
}
The shutDown method is usually called first through the Main and therefore keeps the Active Objects "alive" unwantedly, but sometimes I get the wanted outcome.
Any idea why there is uncertainty about the result?
Below you can see the rest of the classes:
public class MyThreadPool {
ArrayBlockingQueue<Runnable> q;
ArrayBlockingQueue<ActiveObject> activeObjects;
volatile boolean stop;
AtomicInteger count;
Thread t;
Runnable stopTask;
public MyThreadPool(int capacity, int maxThreads) {
activeObjects = new ArrayBlockingQueue<>(maxThreads);
q = new ArrayBlockingQueue<>(capacity);
count = new AtomicInteger(0);
stopTask = ()->stop = true;
t=new Thread(()->{
//System.out.println("Thread-Pool Started");
while(!stop){
//if queue is empty it is gonna be a blocking call
try {
Runnable task = q.take();
if(task==stopTask)
stopTask.run();
else
//size() is atomic integer
if (count.get() < maxThreads) {
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
}
//we will assign the next task to the least busy ActiveObject
else {
int minSize = Integer.MAX_VALUE;
ActiveObject choice = null;
for (ActiveObject a : activeObjects) {
if (a.size() < minSize) {
minSize = a.size();
choice = a;
}
}
choice.execute(task);
}
} catch (InterruptedException e) { }
}
//System.out.println("Thread-Pool Ended");
});
t.start();
}
//execute returns right away - just puts into the queue
public void execute(Runnable r ){
// if capacity is full it is gonna be a blocking call
if(!stop)
try { q.put(r); } catch (InterruptedException e) { }
}
public void shutDownNow(){
activeObjects.forEach(a->a.shutDownNow());
stop = true;
t.interrupt();
}
public void shutDown(){
activeObjects.forEach(a->a.shutDown());
execute(stopTask);
}
public class ActiveObject {
ArrayBlockingQueue<Runnable> q;
volatile boolean stop;
Thread t;
public ActiveObject(int capacity) {
q = new ArrayBlockingQueue<>(capacity);
t=new Thread(()->{
//System.out.println("Active Object Started");
while(!stop){
//if queue is empty it is gonna be a blocking call
try {
q.take().run();
} catch (InterruptedException e) { }
}
//System.out.println("Active Object Ended");
});
t.start();
}
//execute returns right away - just puts into the queue
public void execute(Runnable r ){
// if capacity is full it is gonna be a blocking call
if(!stop)
try { q.put(r); } catch (InterruptedException e) { }
}
public void shutDownNow(){
stop = true;
t.interrupt();
}
public void shutDown(){
execute(()->stop=true);
}
public int size(){
return q.size();
}
}
In your main method you create a thread pool (which also creates and starts tp.t thread), enqueue a task into tp.q, and then call tp.shutDown():
MyThreadPool tp = new MyThreadPool(100, 3);
tp.execute(() -> {...});
tp.shutDown();
Imagine that tp.shutDown() in the main thread is executed before the MyThreadPool.t thread processes the enqueued task:
activeObjects.forEach(a -> a.shutDown());
execute(stopTask);
here activeObjects is empty, you enqueue stopTask into tp.q, and main thread finishes.
Now we only have MyThreadPool.t thread, let's see what it does:
while (!stop) {
try {
Runnable task = q.take();
if (task == stopTask)
stopTask.run();
else
if (count.get() < maxThreads) {
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
}
else {
...
}
} catch (InterruptedException e) {
}
}
At this point q contains 2 tasks: a normal task and stopTask.
In the first loop iteration the normal task is taken from q, and is given for processing to a newly created ActiveObject:
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
new ActiveObject() also creates and starts its own internal ActiveObject.t thread.
The second loop iteration processes stopTask:
if (task == stopTask)
stopTask.run();
which sets stop = true.
As a result, the next check while (!stop) returns false and MyThreadPool.t thread finishes.
Now we only have ActiveObject.t thread, which hasn't been stopped:
while (!stop) {
try {
q.take().run();
} catch (InterruptedException e) {
}
}
here the thread will keep waiting on q.take() forever.
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....
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.
Below code I have written for a deadlock, but for small "for loop" code is not falling in deadlock while when I keep "for loop" till 10 then deadlock is occurring.
Can someone plz explain, why it is showing such behavior ?
public class CustomerUpdateDeadloackThread {
public static void main(String[] args) {
Customer cstmr = new Customer("Peter");
Address adrs = new Address("B-232, Bangalore");
// For loop till 3 is not showing deadlock.
for (int i=0; i<10;i++){
new Thread(new TagObjectsToEachOther(cstmr, adrs)).start();
new Thread(new TagObjectsToEachOther(adrs, cstmr)).start();
}
}
}
interface CustomerUpdater {
public boolean update(Object obj);
}
class TagObjectsToEachOther implements Runnable {
CustomerUpdater taskItem;
Object objToUpdateWith;
public TagObjectsToEachOther(CustomerUpdater cspdtr, Object obj2) {
this.taskItem = cspdtr;
this.objToUpdateWith = obj2;
}
#Override
public void run() {
taskItem.update(objToUpdateWith);
System.out.println(" Task done :" + Thread.currentThread().getName());
}
}
class Address implements CustomerUpdater {
String address;
Customer customer;
public Address(String addrs) {
this.address = addrs;
}
#Override
public boolean update(Object cstmr) {
synchronized (this) {
synchronized ((Customer) cstmr) {
try {
this.customer = (Customer) cstmr;
Thread.sleep(2000); // or else do some other work here
} catch (CustomerUpdateFailureException e) {
e.getCause();
return false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}
}
class Customer implements CustomerUpdater {
String name;
Address address;
public Customer(String nm) {
this.name = nm;
}
#Override
public boolean update(Object adrs) {
synchronized (this) {
synchronized ((Address) adrs) {
try {
this.address = (Address) adrs;
Thread.sleep(2000); // or else do some other work here
} catch (CustomerUpdateFailureException e) {
e.getCause();
return false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}
}
class CustomerUpdateFailureException extends RuntimeException {
private static final long serialVersionUID = 1L;
#Override
public String getMessage() {
return "Uncompitable update";
}
}
You're only going to get a deadlock if one of your threads obtains one monitor and the other thread obtains the other monitor before the first thread obtains the second monitor. The more threads you have obtaining the monitors on the two objects, the more likely it is that one of them will obtain just one lock and be pre-empted before it gets a chance to obtain the second monitor.
In other words, this is fine, and just causes a wait:
Thread A Thread B
Lock X
Lock Y
Lock Y // Blocks (temporary)
Sleep
Lock X
Sleep
Whereas this causes deadlock:
Thread A Thread B
Lock X
Lock Y
Lock Y // Blocks (deadlock)
Lock X // Blocks (deadlock)
If you move your Thread.sleep(2000) call to between your two synchronized statements (in both methods) then you're almost guaranteed to get a deadlock, without any looping at the top level.
I am naive in multi-threading and is trying to learn it's concepts. This is my implementation for Producer-Consumer problem. Please have a look and suggest me if it is incorrect/crude/any other suggestions that could improve my design.
static int data = 0;
static Object obj1 = new Object();
static class Producer implements Runnable {
public void run() {
produce();
}
void produce() {
while (true) {
if (data < 5){
synchronized(obj1){
System.out.println("Producing Data. Now Data is "+data++);
obj1.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
try {
System.out.println("Producer inactive");
synchronized(obj1){
obj1.wait();
}
System.out.println("Producer active");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable{
public void run(){
consume();
}
void consume() {
while (true) {
if (data > 0){
synchronized(obj1){
System.out.println("Consuming Data. Now Data is "+data--);
obj1.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
try {
System.out.println("Consumer Inactive");
synchronized(obj1){
obj1.wait();
}
System.out.println("Consumer Active");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Ok several points. Producer and Consumer usually share a data structure. The use of the static data is very odd and quite frankly makes no sense. Typically what you'll want to share is a data structure like a queue between producer and consumer. The producer will add things on to the tail of the queue and the consumer(s) will draw things from the head of the queue (FIFO - first in first out). Right now I see none of that so what exactly is it producing vs consuming?
A good producer consumer architecture doesn't care too much about what type of data is exchanged so you can pass many different types of things over it. That's where object oriented command architecture will help you out. In this example SomeMessage represents the root of some object hierarchy so a variety of messages can be exchanged.
Here is a simple example of how you should instantiate a Producer-Consumer architecture in your program:
public class SomeClient {
public void start() {
Queue sharedQueue = new LinkedList();
producer = new Producer( sharedQueue );
consumer = new Consumer( sharedQueue );
producer.start();
consumer.start();
}
}
Here is the implementation of that:
public class Producer implements Runnable {
Thread thread;
Queue queue;
public Producer(Queue queue) {
this.queue = queue;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void shutdown() {
thread.interrupt(); // request a shutdown
thread.join(); // make sure we wait until Producer.thread exits before this thread continues
}
public void run() {
try {
while( !Thread.isInterrupted() ) {
SomeMessage message = produceAMessage();
synchronized( queue ) {
queue.add( message );
queue.notifyAll();
}
}
} catch( InterruptedException ex ) {
System.out.println("Producer shutting down per request.");
} finally {
thread = null;
}
}
}
public class Consumer implements Runnable {
Thread thread;
Queue queue;
public Consumer( Queue queue ) {
this.queue = queue;
}
public void start() {
thread = new Thread( this );
thread.start();
}
public void shutdown() {
thread.interrupt(); // request a shutdown
thread.join(); // make sure we wait until Consumer.thread exits before this thread continues
}
public void run() {
try {
while( !thread.isInterrupted() ) {
SomeMessage message = take();
doSomethingWithMessage( message );
}
} catch( InterruptedException ex ) {
System.out.println("Stop processing - consumer per request.");
} finally {
thread = null;
}
}
private SomeMessage take() throws InterruptedException {
synchronized( queue ) {
queue.wait();
return queue.remove();
}
}
}
A couple of things that differ in this implementation. Producer and Consumer share a Queue instance and they use that instance to perform synchronized calls on. That way neither write or read from that structure without owning the lock. After they have either added to the queue (producer) or removed from the queue (consumer) they are free from needing to use synchronization. They are free to process without needing to communicate with each other. They trade instances of SomeMessage between each instance by adding to the tail and drawing from the head.
The take() method is very important in this code. Without the helper method you can't process the message AND release the lock. This important so that your Consumer can receive a message and let go of the lock to allow other Producers/Consumers to add/remove messages while this particular Consumer is processing a message. This keeps throughput as fast as possible.
And yes I said Producers. This architecture allows for multiple Producers AND multiple Consumers without needing to change the internals of either Producer or Consumer.
Notice that catching InterruptedException is outside the while loop. This is very important if you want a predictable program that shuts down cleanly. An InterruptedException and interrupted concept is the heart of well behaving Java threads. If you don't know under what conditions this exception is generated you'll never understand multi-threaded apps in Java. It's not a random occurrence. Java threads can't be stopped programatically. Another thread must request it to interrupt itself. And the thread must obey the request or else it won't stop. So if we get one. Shutdown. In this program we'll only get it when we call wait or notify which means while we're processing a message we won't be interrupted. Consumers will finish processing messages before halting.
Finally, it's actually much easier to implement a Producer-Consumer relationship given the concurrency libraries in Java, but this is a good example of how you do it at the lowest level of Java to understand what those libraries are doing for you.
Encapsulating the consume and produce behaviors could be more more reusable. In the code below I decoupled the shared resource synchronization issues from consumer/producer thread which could be useful in solving similar problems like Object Pool and Connection Pool.
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
public static void main(String[] args) {
SyncQueue syncQueue = new SyncQueue(1);
Producer producer = new Producer(syncQueue , 10);
Consumer consumer = new Consumer(syncQueue,10);
producer.start();
consumer.start();
}
}
class SyncQueue {
private Queue<Integer> queue = new LinkedList<Integer>();
private Integer size;
public SyncQueue(Integer size) {
super();
this.size = size;
this.signalledBefore = false;
}
public synchronized void put(Integer data){
while(queue.size() == size){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(data);
notifyAll();
}
public synchronized Integer get(){
while(queue.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Integer data = queue.remove();
notifyAll();
return data;
}
}
class Producer extends Thread{
private SyncQueue syncQueue;
private Integer size;
public Producer(SyncQueue syncQueue, Integer size) {
this.syncQueue = syncQueue;
this.size = size;
}
#Override
public void run() {
for (Integer i = 0; i < size; i++) {
syncQueue.put(i);
System.out.println("Produced:" + i);
try {
sleep((int)Math.random()*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private SyncQueue syncQueue;
private Integer size;
public Consumer(SyncQueue syncQueue, Integer size) {
this.syncQueue = syncQueue;
this.size = size;
}
#Override
public void run() {
for (Integer i = 0; i < size; i++) {
try {
sleep((int)Math.random()*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumed:" + syncQueue.get());
}
}
}