Reputation: 11
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
Upvotes: 0
Views: 87
Reputation: 542
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.
Upvotes: 1