I'm working on a variant of the producer consumer problem in Java. I have a producer thread creating objects, that are put into an priority blocking queue, and then passed into the main container, the controller, which is a bounded buffer.
The reason for the queue is that when the main container has a certain % of Object A, it will only accept objects of type B, and some other scenarios that we have been asked to look at.
I'm having trouble figuring out what is going wrong with the code, the debugger is just jumping from in.offer in InQueue, and in.push in Producer. Any direction or advice would be appreciated.
import java.util.concurrent.PriorityBlockingQueue;
public class InQueue implements Runnable {
Controller c;
private PriorityBlockingQueue in;
public InQueue(Controller c) {
this.c = c;
in = new PriorityBlockingQueue();
}
public void push(C c) {
in.offer(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
C temp = (C) in.take(); //will block if empty
c.arrive(temp);
} catch (InterruptedException e) {} // TODO
}
}
}
public class Controller {
private BoundedBuffer buffer;
private int used;
Controller(int capacity) {
this.buffer = new BoundedBuffer(capacity);
used = 0;
}
public void arrive(C c) {
try {
buffer.put(c);
used++;
} catch (InterruptedException e) { } //TODO
}
public C depart() {
C temp = null; //BAD IDEA?
try {
temp = (C)buffer.take();
used--;
} catch (InterruptedException e) { } //TODO
return temp; //could be null
}
}
Your code is not compiling because of the wrong way your using generics. Another thing is that there is no default implementation of BoundedBuffer. Below I made a working implementation for the producer - consumer problem below with blocking queues. Have a look and correct your mistakes.
package concurrency;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Producer<T> {
private final BlockingQueue<T> queue;
private final Consumer consumer;
private static volatile boolean isShutdown;
private final static Object lock = new Object();
public Producer() {
this.queue = new LinkedBlockingQueue<T>();
this.consumer = new Consumer();
}
public void start() {
consumer.start();
}
public void stop() {
synchronized (lock) {
isShutdown = true;
}
consumer.interrupt();
}
public void put(T obj) throws InterruptedException {
synchronized (lock) {
if (isShutdown)
throw new IllegalStateException("Consumer Thread is not active");
}
queue.put(obj);
}
private class Consumer extends Thread {
public void run() {
while (true) {
synchronized (lock) {
if (isShutdown)
break;
}
T t = takeItem();
// do something with 't'
if(t!=null)
printItem(t);
}
}
private void printItem(T t) {
System.out.println(t);
}
private T takeItem() {
try {
return queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return null;
}
}
public static void main(String[] args) throws InterruptedException {
Producer<Integer> producer = new Producer<Integer>();
producer.start();
for (int i = 0; i <20; i++) {
producer.put(i);
if (i >= 7)
Thread.sleep(500);
}
producer.stop();
}
}
Related
I want to call a method in java but synchronized and first-in-first-out.
Currently I call the method like so:
synchronized (synchronizeObject) {
executeMethode(object1, object2);
}
I found out, that synchronized does not actually care in what order something is added.
Is there an easy way to force FIFO?
I do not think ArrayBlockingQueue is applicable here, At least not in a way I see it, but I may be wrong
Here is a snippet:
public class AppTest {
#Test
void test() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(8);
FairLockedMethod<Integer> method = new FairLockedMethod<>() {
#Override
protected void lockedMethod(Integer i) {
System.out.println(i);
try {
Thread.currentThread().wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for (int i = 0; i < 16; i++) {
int n = i;
pool.submit(() ->method.run(n));
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
}
public static abstract class FairLockedMethod<T> {
protected abstract void lockedMethod(T value);
private final ReentrantLock lock = new ReentrantLock(true);
private final Condition condition = lock.newCondition();
private final Queue<Thread> queue = new LinkedBlockingDeque<>();
public void run(T value) {
queue.offer(Thread.currentThread());
lock.lock();
try {
while (queue.peek() != Thread.currentThread()) {
condition.await();
}
queue.poll();
condition.signalAll();
lockedMethod(value);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
}
It is not most efficient implementation, but simplest I can come with.
I have a code and I want to ensure the order in which the robot's legs move using wait() and notify(). Here is the code:
public class Leg implements Runnable {
private final Object monitor = new Object();
private final String name;
public Leg(String name) {
this.name = name;
}
#Override
public void run() {
while (true) {
synchronized (monitor) {
move();
monitor.notify();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void move() {
System.out.println(name);
}
public static void main(String[] args) {
CompletableFuture.allOf(
CompletableFuture.runAsync(new Leg("left")),
CompletableFuture.runAsync(new Leg("right"))
).join();
}
}
Right now the output is the below:
left
right
// and then it stops moving.
I want the code continue moving (not only once). That's why it's interesting for me what am I doing wrong?
You have 2 Leg object with 2 threads to process, for each thread you have a monitor object, so when you use notify and wait, it just effects to one thread (which thread is running currently):
synchronized (monitor) {
move();
monitor.notify(); // notify current thread, it's no meaning
try {
monitor.wait(); // current thread will block here and there is no thread wake up it
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Maybe it's what you need:
import java.util.concurrent.CompletableFuture;
public class Leg implements Runnable {
private final String name;
private Leg nextLeg;
private volatile boolean active;
public Leg(String name) {
this.name = name;
}
public void setNextLeg(Leg nextLeg) {
this.nextLeg = nextLeg;
}
public void active() {
synchronized (this) {
this.active = true;
notify();
}
}
#Override
public void run() {
while (true) {
try {
synchronized (this) {
while (!active) {
wait();
}
move();
active = false;
nextLeg.active();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
private void move() {
System.out.println(name);
}
public static void main(String[] args) {
Leg left = new Leg("left");
Leg right = new Leg("right");
left.setNextLeg(right);
right.setNextLeg(left);
left.active();
CompletableFuture.allOf(
CompletableFuture.runAsync(left),
CompletableFuture.runAsync(right)
).join();
}
}
I am new to java thread. I am unable to give the lock back to the thread from the main thread in the following code. I am getting the undesired output because i am unable to unlock the thread. I want thread to increment the value using thread (goes to wait state after that) and after printing the value, release the lock to print the next incremented value.
class Foo implements Runnable
{
public volatile int value=0,i=0;
Thread t=new Thread();
public void method(Thread t)
{
this.t = t;
}
#Override
public synchronized void run()
{
while(i<3)
{
value++;//receive and process ACK
i++;
try
{
System.out.println("im thread here");
wait();
System.out.println("passed wait");
}
catch(InterruptedException ex){
}
System.out.println("im notified");
}//while
//}//sync
}//run method
public int getValue()
{
try
{
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println(e);
}
return value;
}
}//class foo
public class ThreadTest
{
public static int value1,times=0;
public static void main(String[] args)
{
Foo foo=new Foo();
Thread t=new Thread(foo);
foo.method(t);
t.start();
while(times<3)
{
synchronized(t)
{
value1=foo.getValue();
times++;
System.out.println(value1);
System.out.println(t.getState());
try
{
t.notify();
System.out.println("Notify is reached");
}
catch(IllegalMonitorStateException ex)
{
System.out.println("Thread is blocked");
}
}//sync
}//while
}//main
}//mclasss
Are you trying to do something like this? If you really must use wait/notify & want to use Runnable.
I added a wait block, otherwise the main thread may finish before the background thread increments the value.
class Foo implements Runnable {
public volatile int value = 0, i = 0;
private Thread backgroundThread;
public void setThread(Thread thread) {
this.backgroundThread = thread;
}
#Override
public void run() {
synchronized (backgroundThread) {
while (i < 2) {
value++;
i++;
backgroundThread.notify();
try {
System.out.println("background thread wait start");
backgroundThread.wait();
System.out.println("background thread notified");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
public int getValue() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
public class ThreadTest {
public static int value1, times = 0;
public static void main(String[] args) {
Foo foo = new Foo();
final Thread thread = new Thread(foo);
foo.setThread(thread);
thread.start();
while (times < 3) {
synchronized (thread) {
value1 = foo.getValue();
times++;
System.out.println(value1);
System.out.println(thread.getState());
thread.notify();
try {
thread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Or you can extend thread:
class BackgroundThread extends Thread {
public volatile int value = 0, i = 0;
#Override
public synchronized void run() {
while (i < 2) {
value++;
i++;
notify();
try {
System.out.println("background thread wait start");
wait();
System.out.println("background thread notified");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public int getValue() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
public class ThreadTest {
public static int value1, times = 0;
public static void main(String[] args) {
BackgroundThread backgroundThread = new BackgroundThread();
backgroundThread.start();
while (times < 3) {
synchronized (backgroundThread) {
value1 = backgroundThread.getValue();
times++;
System.out.println(value1);
System.out.println(backgroundThread.getState());
backgroundThread.notify();
try {
backgroundThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
It is very unclear what you really want to do but we will assume here that you want to run a thread in the background which should run only when its spawner (let's say the main thread) allows it to.
The JDK has several tools for this already, no need to rely on the low level wait() and notify{,All}() methods.
One example of such a primitive is a CountDownLatch. It is a one-use entity which allows you to specify the times a given set of threads should countDown() it before any threads .await()ing for them can trigger.
In combination with the multithread handling classes which appeared as far back as Java 1.5, this means you could do something like this:
// Implementation of a Runnable waiting for the counter to trigger
public final class MyWaitingClass
implements Runnable
{
private final CountDownLatch latch;
public MyWaitingClass(final CountDownLatch latch)
{
this.latch = latch;
}
#Override
public void run()
{
try {
latch.await();
// do whatever is necessary
} catch (InterruptedException e) {
// Argh; interrupted before the latch was released
Thread.currentThread().interrupt();
}
}
}
// In the main class:
final ExecutorService executor = Executors.newSingleThreadPool();
final CountDownLatch latch = new CountDownLatch(1);
final Runnable runnable = new MyWaitingClass(latch);
executor.submit(runnable);
// do whatever is needed; then:
latch.countDown();
I have been working on some code, but I need help.
I have created one producer and one consumer, however I need to create multiple consumers who will consume the specific String from the producer e.g. I need a consumer that will consume specifically 'Move Left Hand'.
Contained in the code is the buffer, producer, consumer and the main. I am not sure how to notify the correct consumer and compare the string that needs to be consumed. As it stands I only have one consumer.
public class iRobotBuffer {
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
public class iRobotConsumer implements Runnable {
private iRobotBuffer robotBuffer;
public iRobotConsumer(iRobotBuffer robotBuffer){
this.robotBuffer = robotBuffer;
}
public void run() {
Random random = new Random();
for (String message = robotBuffer.take();
! message.equals("DONE");
message = robotBuffer.take()) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
public class iRobotProducer implements Runnable {
private iRobotBuffer robotBuffer;
private int number;
public iRobotProducer(iRobotBuffer robotBuffer)
{
this.robotBuffer = robotBuffer;
//this.number = number;
}
public void run() {
String commandInstructions[] = {
"Move Left Hand",
"Move Right Hand",
"Move Both Hands",
};
int no = commandInstructions.length;
int randomNo;
Random random = new Random();
for (int i = 0;
i < commandInstructions.length;
i++) {
randomNo =(int)(Math.random()*no);
System.out.println(commandInstructions[randomNo]);
robotBuffer.put(commandInstructions[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
robotBuffer.put("DONE");
}
}
public class iRobot
{
public static void main(String[] args)
{
iRobotBuffer robotBuffer = new iRobotBuffer();
(new Thread(new iRobotProducer(robotBuffer))).start();
(new Thread(new iRobotConsumer(robotBuffer))).start();
}//main
}//class
The problem is your iRobotBuffer class. It needs to be a queue to support multiple producer / consumers. I've provided the code for such a queue, but java already has an implementation (BlockingDeque<E>).
public class BlockingQueue<T> {
private final LinkedList<T> innerList = new LinkedList<>();
private boolean isEmpty = true;
public synchronized T take() throws InterruptedException {
while (isEmpty) {
wait();
}
T element = innerList.removeFirst();
isEmpty = innerList.size() == 0;
return element;
}
public synchronized void put(T element) {
isEmpty = false;
innerList.addLast(element);
notify();
}
}
As I understand, you would like 3 consumers, one for each move instruction.
You can use an ArrayBlockingQueue from the java.util.concurrent package, in place of the iRobotBuffer class. By the way, you can have a look at the other concurrent collections provided - one may sweet you better.
Then for the consumer, you can peek() at what is in the queue and test if it matches the requirements and then poll().
I have this code:
private void doSomething() throws InterruptedException {
WorkerThread w= new WorkerThread(this);
w.start();
synchronized (synchObj) {
while (!isDone) {
synchObj.wait();
}
}
System.out.println("End");
}
Where the calling class implements a method that calls notifyAll() on synchObj when WorkerThread instance is done. Everything works pretty much as expected except the final call to System.out.println("End"); is never called. Why is that?
Edit: Here's the rest of the code:
public class App implements Notifee {
private boolean isDone = false;
private final Object synchObj = new Object();
/**
* #param args
*/
public static void main(String[] args) {
App app = new App();
for (int i = 0; i < 5; i++) {
try {
app.doSomething();
} catch (InterruptedException e) {
System.err.println("Didn't even start");
e.printStackTrace();
}
}
}
private void doSomething() throws InterruptedException {
WorkerThread w= new WorkerThread(this);
w.start();
synchronized (synchObj) {
while (!isDone) {
synchObj.wait();
}
}
System.out.println("End");
}
#Override
public void letMeKnow() {
synchronized (synchObj) {
synchObj.notifyAll();
}
}
}
public class WorkerThread extends Thread {
private Notifee n;
public WorkerThread(Notifee n){
this.n = n;
}
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
n.letMeKnow();
}
}
You are never setting isDone to true. Also you should make it volatile. You probably should add:
#Override
public void letMeKnow() {
isDone = true;
synchronized (synchObj) {
synchObj.notifyAll();
}
}
Edit: If you want to just wait for the worker thread to finish call:
w.join();