Edit:
I have a producer class that send some data to the SharedBuffer class. This data is added to an ArrayList with the limit set to 100. There is no problem with adding data to said list, but the consumer class does not manage to get any of the data out of the list.
No output is produced at all (no null or errors).
Edit 2: The method for putting data inside the array was added.
SharedBuffer class:
static final int RESOURCE_LIMIT = 100;
private List<String> data = new ArrayList<String>();
// private boolean done = false;
public boolean isFull(){
return data.size() >= RESOURCE_LIMIT;
}
public boolean isEmpty(){
return data.size() <= 0;
}
public synchronized void putData(String s){
while(this.isFull()){
try{
wait();
}catch(InterruptedException e){
//
e.printStackTrace();
}
}
data.add(s);
//size works and there is data in list.
//System.out.println(data.size() + data.get(0));
public boolean isEmpty(){
return data.size() <= 0;
}
public synchronized String getData(){
while(this.isEmpty()){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
String s_data = (String)(data.get(0));
if(s_data != null){
data.remove(s_data);
System.out.println(s_data);
}
return s_data;
}
Consumer class:
#Override
public void run() {
while(true){
String line = buffer.getData();
if(line != null){
System.out.println(line);
//do stuff with the data.
}
}
}
Change your code (add notyfyAll() invokation)
public synchronized void putData(String s){
while(this.isFull()){
try{
wait();
}catch(InterruptedException e){
//
e.printStackTrace();
}
}
data.add(s);
notifyAll();
}
public synchronized String getData(){
while(this.isEmpty()){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
String s_data = (String)(data.get(0));
if(s_data != null){
data.remove(s_data);
System.out.println(s_data);
}
notifyAll();
return s_data;
}
Also you should synchronize isEmpty and isFull methods because the access to data.
Related
new to multithreading. I wrote this program which should be a solution to the producer-consumer problem. The problem is that both a producer and a consumer end up in the waiting state. What seems to be wrong? (And everything else what is wrong ^_^) Thanks in advance.
Main class:
package producer.consumer2;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Buffer<Integer> bf = new Buffer<>(10);
Producer prod = new Producer(bf);
Consumer cons = new Consumer(bf);
prod.setConsumer(cons);
cons.setProducer(prod);
new Thread(prod).start();
new Thread(cons).start();
if(quitInput()) {
prod.terminate();
cons.terminate();
}
}
private static boolean quitInput() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
do {
if(line.toLowerCase().equals("q") || line.toLowerCase().equals("quit")) {
sc.close();
return true;
}
line = sc.nextLine();
} while(true);
}
}
Buffer class:
package producer.consumer2;
import java.util.ArrayList;
public class Buffer<E> {
private final int MAX_LENGTH;
private ArrayList<E> values;
public Buffer(int length){
MAX_LENGTH = length;
values = new ArrayList<E>(length);
}
public synchronized void add(E e) {
if(values.size() < MAX_LENGTH) {
values.add(e);
System.out.println(values);
} else {
throw new RuntimeException("Buffer is full at the moment.");
}
}
public synchronized boolean isEmpty() {
return values.size() == 0;
}
public synchronized boolean isFull() {
return values.size() >= MAX_LENGTH ? true : false;
}
public synchronized E remove(int index) {
E val = values.remove(index);
System.out.println(values);
return val;
}
}
Consumer class:
package producer.consumer2;
public class Consumer implements Runnable {
private final Buffer<Integer> bf;
private volatile boolean running = true;
private Producer prod;
public Consumer(Buffer<Integer> bf) {
this.bf = bf;
}
public void setProducer(Producer prod) {
this.prod = prod;
}
#Override
public void run() {
int sum = 0;
int counter = 0;
while (running) {
if (bf.isEmpty()) {
if (prod != null) {
synchronized (prod) {
prod.notify();
}
}
myWait(0);
} else {
sum += bf.remove(0);
counter++;
}
}
System.out.println("for first " + counter + " nums an avg = " + ((double) sum / counter));
}
private void myWait(long millisecs) {
System.out.println("consumer is waiting.");
try {
synchronized (this) {
this.wait(millisecs);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("consumer is NOT waiting.");
}
public void terminate() {
this.running = false;
}
}
Producer class:
package producer.consumer2;
public class Producer implements Runnable {
private final Buffer<Integer> bf;
private volatile boolean running = true;
private Consumer cons;
public Producer(Buffer<Integer> bf) {
this.bf = bf;
}
public void setConsumer(Consumer cons) {
this.cons = cons;
}
#Override
public void run() {
int counter = 1;
while (running) {
if (bf.isFull()) {
if (cons != null) {
synchronized (cons) {
cons.notify();
}
}
myWait(0);
} else {
bf.add(counter);
counter++;
}
}
}
private void myWait(long millisecs) {
System.out.println("producer is waiting.");
try {
synchronized (this) {
this.wait(millisecs);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("producer is NOT waiting.");
}
public void terminate() {
this.running = false;
}
}
Looks like a regular case of 'missed signal'. Since both consumer and producer just wait without checking a condition, yu have no way to ensure the notify actually happens during the waiting.
e.g. in Consumer :
if (prod != null) {
synchronized (prod) {
prod.notify();
}
}
myWait(0);
Note that if, after prod.notify() the Production thread does all of its work, and notifies the consumer, before it even starts waiting, the consumer will start waiting for a signal that's already been given, and missed.
Always take into account that waiting may not be needed anymore. So always check a condition before even starting to wait. In your case here, the consumer should not even begin waiting if the buffer is full. And likewise the producer should not start waiting if the buffer is empty.
It's also possible to get spurious wake ups. So you'll have to re-check the condition when returning from waiting. The typical idiom is this :
synchronized(monitor) {
while (!stateBasedCondition) {
monitor.wait();
}
}
How could I move most of the code into one function or otherwise consolidate it? I'm not so happy with so much duplicate code. Event IntelliJ complains about it...
public boolean closeTrade(Trade trade) {
for (int i=0; i< NUM_CHECKS; i++) {
if (closeBrokerTrade(trade)) return true; // quit loop if successfully closed
//region sleep between checks
if (i < NUM_CHECKS -1) try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
throw propagate(e);
}
//endregion
}
return false;
}
public boolean closeTrade(String ticket) {
for (int i=0; i< NUM_CHECKS; i++) {
if (closeBrokerTrade(ticket)) return true; // quit loop if successfully closed
//region sleep between checks
if (i < NUM_CHECKS -1) try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
throw propagate(e);
}
//endregion
}
return false;
}
protected abstract boolean closeBrokerTrade(Trade trade);
protected abstract boolean closeBrokerTrade(String ticket);
In Java 8 you could pass the correct version of closeBrokerTrade as a lambda:
Declare the function like this:
public boolean closeTrade( BooleanSupplier f) {
// ...
if (f.getAsBoolean()) return true; // quit loop if successfully closed
// ...
return false;
}
And call it like that:
c.closeTrade( () -> c.closeBrokerTrade(new Trade()) );
c.closeTrade( () -> c.closeBrokerTrade("123") );
I need to see the implementation of closeBrokerTrade to be sure about the behaviour, but I would do something like this:
public boolean closeTrade(Trade trade) {
String ticket = ...// generate ticket from trade in whatever way you do it, e.g. trade.getTicket() or trade.toString(), etc. etc.
return closeTrade(ticket);
}
public boolean closeTrade(String ticket) {
for (int i=0; i< NUM_CHECKS*3; i++) {
if (closeBrokerTrade(ticket)) return true; // quit loop if successfully closed
//region sleep between checks
if (i < NUM_CHECKS -1) try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
throw propagate(e);
}
//endregion
}
return false;
}
Correct me if I am wrong or if it is the case that you obtain the trade from the ticket.
If that's not possible, here is my suggestion:
Use generics to represent parameterized trade closing classes like this:
public abstract class ClosingTradeStrategy<T> {
public boolean closeTrade(T trade) {
for (int i=0; i< NUM_CHECKS*3; i++) {
if (closeBrokerTrade(trade)) return true; // quit loop if successfully closed
//region sleep between checks
if (i < NUM_CHECKS -1) try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
throw propagate(e);
}
//endregion
}
return false;
}
protected abstract boolean closeBrokerTrade(T trade);
}
then you can use this to implement different trade closing strategies like this:
public class StringClosingTradeStrategy extends ClosingTradeStrategy<String> {
#Override
protected boolean closeBrokerTrade(String trade) {
... // implement
}
}
public class TradeClosingTradeStrategy extends ClosingTradeStrategy<Trade> {
#Override
protected boolean closeBrokerTrade(Trade trade) {
... // implement
}
}
The advantage of the second approach is that it is easily extensible to other closing strategies.
Use interfaces, as you would if you were to use a Comparator<T>:
private static interface CloseBrokerTradeChecker <T> {
boolean closeBrokerTrade(T t);
}
private static class CloseBrokerTradeCheckerTrade
implements CloseBrokerTradeChecker<Trade> {
#Override
boolean closeBrokerTrade(Trade trade) { ... }
}
private static class CloseBrokerTradeCheckerTicket
implements CloseBrokerTradeChecker<String> {
#Override
boolean closeBrokerTrade(String ticket) { ... }
}
private <T> boolean closeTrade(T t, CloseBrokerTradeChecker<T> checker) {
for (int i=0; i< NUM_CHECKS*3; i++) {
if (checker.closeBrokerTrade(t)) return true; // quit loop if successfully closed
//region sleep between checks
if (i < NUM_CHECKS -1) try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
throw propagate(e);
}
//endregion
}
return false;
}
public boolean closeTrade(Trade trade) {
// TODO: extract CloseBrokerTradeCheckerTrade as a static final variable
return closeTrade(trade, new CloseBrokerTradeCheckerTrade());
}
public boolean closeTrade(String ticket) {
return closeTrade(ticket, new CloseBrokerTradeCheckerTicket());
}
i have made a program and expecting output like this :
A
1
a
B
2
b
C
3
c
...
E
5
e
here is my code i think am getting starvation problem plz help me
class Product {
static boolean flag1, flag2, flag3;
synchronized void printLwrAlpha(char value) {
// System.out.println(flag3+": inside lwr_alpha");
if (!flag3)
try {
wait();
} catch (Exception ex) {
System.out.println(ex);
}
System.out.println(value);
flag3 = false;
flag1 = false;
System.out.println("before notify");
notify();
System.out.println("after notify");
}
synchronized void printUprAlpha(char n) {
// System.out.println(flag1+": inside upr_alpha");
if (flag1)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
System.out.println(n);
// System.out.println(num);
flag1 = true;
flag2 = true;
notify();
}
synchronized void printNum(int num) {
// System.out.println(flag2+": inside num");
if (!flag2)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
// System.out.println(n);
System.out.println(num);
flag2 = false;
flag3 = true;
notify();
}
}
class PrintNum implements Runnable {
Product p;
PrintNum(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++)
p.printNum(i);
}
}
class PrintLwrAlpha implements Runnable {
Product p;
static char ch = 'a';
PrintLwrAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printLwrAlpha(c);
}
}
}
class PrintUprAlpha implements Runnable {
Product p;
static char ch = 'A';
PrintUprAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printUprAlpha(c);
}
}
}
public class MainClass1 {
public static void main(String ar[]) {
Product p = new Product();
new PrintNum(p);
new PrintUprAlpha(p);
new PrintLwrAlpha(p);
}
}
i am getting this output:
run:
A
1
B
2
C
3
D
4
E
5
a
before notify
after notify
i think after this program is going in to starvation
Replace all your ifs, e.g.
if (!flag3)
with while loops
while (!flag3)
If I understand correctly your problem is that you're trying to use a single wait object with multiple threads. The common scenario for wait/notify is as follows: the one thread is waiting for resource to become available while the second thread produces the resource and notifies the first thread.
In code it may look like this:
class ResourceFactory {
public synchronized void produce()
{
// make the resource available
obj.notify();
}
public synchronized void consume()
{
if( /* resource is not available */ ) {
obj.wait();
}
// do something with resource
}
}
When multiple threads are trying to wait on a single object the problem is that it's up to implementation which thread would be awaken after notify call. I think you should make 3 different objects and do something like this:
// thread 1
obj1.wait();
obj2.notify()
// thread 2
obj2.wait();
obj3.notify()
// thread 3
obj3.wait();
obj1.notify()
Be careful and try not to deadlock your code.
And at last your code. First two threads are waiting and awaken each other despite the flags. And when the third thread is awaken there's no thread to notify it. So it's a classical deadlock.
class NaiveSQ<E> {
boolean putting = false;
E item = null;
public synchronized E take() throws InterruptedException {
while (item == null)
wait();
E e = item;
item = null;
notifyAll();
return e;
}
public synchronized void put (E e) throws InterruptedException {
if (e == null)
return;
while (putting)
wait();
putting = true;
item = e;
notifyAll();
while (item != null)
wait();
putting = false;
notifyAll();
}
}
class Producer implements Runnable {
int id = -1;
int limit = 1;
Producer(int x) {
id = x;
}
public void run() {
System.out.printf("I am producer number %d\n", id);
for (int i=0; i<limit; i++) {
Integer I = new Integer(i);
try {
Test.queue.put(I);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
class Consumer implements Runnable {
int id = -1;
Consumer(int x) {
id = x;
}
public void run() {
try {
Integer I = Test.queue.take();
System.out.printf(
"I am consumer number %d - I read %d\n", id, I.intValue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
public class Test{
static NaiveSQ<Integer> queue;
public static void main (String [] args){
System.out.println("hello from Java");
Thread p = new Thread(new Producer(1));
p.start();
for (int i=0; i<1; i++) {
Thread c = new Thread(new Consumer(i));
c.start();
}
}
};
Also why does the exception contain null?
This is an implementation from http://www.cs.rice.edu/~wns1/papers/2006-PPoPP-SQ.pdf listing 3
I get output as
hello from Java
I am producer number 1
null
null
why do I get null?
You haven't initated the queue in your main method. I guess you get a NullPointerException since the queue object is never created and the Producer and Consumer refers to the queue which is null.
Even if you initialize the queue properly, still your implementation has a major issue. If the Consumer thread tries to take an item when the queue is empty (which is totally possible according to your code), then Consumer thread enters into an indefinite wait holding the lock to the object. Producer thread can never put an item to the queue. The whole thing will halt.
I created a stack class like this. Some times it runs and sometimes it will through ArrayIndexOutofBoundException. What's wrong in threading? Couldn't understand please help.
public class StackImpl<E> implements Stack<E>{
private E[] stackArray;
private int topOfStack;
public StackImpl(int size) {
stackArray = (E[]) new Object[size];
topOfStack = -1;
}
public synchronized void push(E e) {
while (isFull()) {
try {
System.out.println("stack is full cannot add " + e);
wait();
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
stackArray[++topOfStack] = e;
System.out
.println(Thread.currentThread() + " :notifying after pushing");
notify();
}
public boolean isEmpty() {
return topOfStack == 0;
}
public synchronized E pop() {
while (isEmpty()) {
try {
System.out.println("stack is empty cannot pop ");
wait();
} catch (InterruptedException e) {
}
}
System.out.println(topOfStack);
E element = stackArray[topOfStack];
stackArray[topOfStack--] = null;
System.out.println(Thread.currentThread() + " notifying after popping");
notify();
return element;
}
public boolean isFull() {
return topOfStack >= stackArray.length-1;
}
public static void main(String[] args) {
final Stack<Integer> stack = new StackImpl<Integer>(10);
(new Thread("Pusher") {
public void run() {
while (true) {
stack.push(10);
}
}
}).start();
(new Thread("Popper") {
public void run() {
while (true) {
stack.pop();
}
}
}).start();
}
}
You set
topOfStack = -1;
in the constructor of StackImpl, yet your isEmpty method checks for 0:
public boolean isEmpty() {
return topOfStack == 0;
}
So the while loop will fall through on first pop, if the pusher hasn't added any values yet:
public synchronized E pop() {
while (isEmpty()) {
try {
System.out.println("stack is empty cannot pop ");
wait();
} catch (InterruptedException e) {
}
}
Set the topOfStack to 0 on the constructor and it should work.
Edit: come to think of it, instead change the isEmpty -method to return topOfStack < 0;, and leave the topOfStack = -1; in your constructor... otherwise element in index 0 is never popped.