Getting an infinite loop while trying to remove from a queue - java

I'm modeling a fastfood drive-through using a priority queue of Event objects (yep, homework). There are three stations, an order, payment and collection station, each with their own queues. I'm having an issue removing an item from the collection station (the last station visited by a Customer). When the collection queue fills up, the simulation begins to loop indefinitely and the timer no longer increments. I assume it's because of this line:
public void processFoodCollection(Customer c, Event e) {
collection.remove(c);//this is the issue I believe
collection.setServerStatus(false);
However, if I attempt to use my standard remove() method (which just calls queue.poll() in the station class), it returns null. I have no idea why this would happen after having just added to the queue, it's given me zero problems any other time I've used it at the other stations (and I just copy-pasted the methods for each station class, they're all identical). I'd really appreciate any help on identifying what is causing this loop, or, if it is the remove(c), how I can fix this.
Here's my Restaurant class (contains the simulation, lazy I know), but hopefully it's not necessary to look at since my documentation isn't complete yet: http://pastebin.com/cHj3xqJN[1]
Here's the method in particular I'm having issue with (collection is a CollectionStation var composed of a queue field, the remove(Customer c) and remove() methods are just for access to the queue methods):
public void processFoodCollection(Customer c, Event e) {
collection.remove(c);//Customer c should be head of queue
collection.setServerStatus(false);//cashier not helping anyone
if (collection.getQueueSize() < 2) {
//process event if room available in collection queue
collection.add(payment.remove());//remove customer from payment queue, add to collection queue
payment.setServerStatus(false);
if (!collection.getServerStatus())
createFinishCollection(collection.peek());//creates event to be processed in the future
//generate new finish payment event for new head of payment queue
if (payment.getQueueSize()>0) {
double b = this.exponentialPay.next();//minutes until finished paying
while (b == 0.0) {
b = this.exponentialPay.next();//ensure return > 0.0
}
createFinishPayment(b, payment.peek());
}
//check if head of order queue can move up
if (order.getQueueSize() > 0) {
if (order.peek().getTimeFinished() == this.clockTime && order.getServerStatus()) {
processFinishOrder(order.peek(), eventList.peek());
} else if (!order.getServerStatus()) {
double timeToOrder = (order.peek().getOrderSize() * this.timeToOrderItem);
createFinishOrder(timeToOrder, order.peek());
}
}
}
}//end method processFoodCollection
If I try to use the remove() method, I get a null pointer exception at:
Event newE = new Event(Events.FINISHFOODCOLLECTION, this.clockTime + (c.getOrderSize() * this.timeToProcessItem), c);
from the null customer object (c). This traces back to the createFinishCollection() method call in the above code. So this is how I know I get a null from calling remove, but I don't understand why my queue would say it's empty when I just added to it. Is there some trick to look out for when indirectly removing data structure elements?
Here's the remove method I'm calling (in the CollectionStation class):
/**
* Removes and returns object at front of queue.
* #return
*/
public Customer remove() {
return customerQueue.poll();
}//end method remove
I'm honestly pretty stumped why this wouldn't work. Any guidance would be appreciated (not looking for answers, just help).

Related

Why does creating a copy of an object still alter instance variables of original object?

I have two classes. Class Algorithm implements a method findIntersections() which is a sweep line algorithm to check for intersections in O(nLogN) time.
It also implements a function addSegments which adds objects of type Segment (two points) to a priority Queue based on the x coordinate.
public class Algorithm {
public PriorityQueue pQueue = new PriortiyQueue();
//This function adds objects of type Segments to a priority queue
public void addSegments(List<Segment> segments) {
pQueue.add(segments);
//do something
}
//This function implements a sweep line algorithm to check for Intersections.
public void findIntersection() {
while (!pQueue.isEmpty()) {
p.poll(); //removes element from Queue
// do something
}
}
}
The other class Model loads data from a CSV file into the priority Queue. This is an intensive process which I only want to do once.
On the other hand, checkForCollissions is called millions of times.
I want to check for collisions between the supplied segment and the rest of the segments added in the priority queue from the csv file
I do not want to be adding elements to the priority queue from scratch each time. This would not be feasible.
public class Model {
public Algorithm algoObj = new Algorithm();
public ArrayList<Segment> algoObj = new ArrayList<>();
public ArrayList<Segment> segments = new ArrayList<>();
public ArrayList<Segment> single_segment = new ArrayList<>();
public boolean loadCSV() {
//read csv file
while ((strLine = br.readLine()) != null) {
segments.add(new Segment()); //Add all segments in CSV file to ArrayLisyt
algo.addSegments(segments); //Adds 4000 objects of type segment to priority Queue
}
}
//This function is called millions of times
public boolean checkForCollisions(segment_to_check) {
single_segment.add(segment_to_check); //Add 1 segment.
algoObj.addSegments(single_segment); //Adds 1 object of type segment to priority Queue
algoObj.findIntersection();
single_segment.remove(new Segment()); //Remove above segment to get back to original data
}
}
TL;DR
The problem I am having is that after the first call of checkForCollisions the priority queue has changed since findIntersection() works by polling elements from the queue, thus altering the queue.
How do I keep the priority queue created by algoObj.addSegments() from changing between function calls?
Does this have to do witch shallow and deep copying as explained here?
I tried creating a copy of the queue at the beginning of the function and then altering the copy:
public boolean checkForCollisions(segment_to_check) {
Algorithm copy = algoObj;
single_segment.add(segment_to_check); //Add 1 segment.
copy.addSegments(single_segment); //Adds 1 object of type segment to priority Queue
copy.findIntersection();
single_segment.remove(new Segment()); //Remove above segment to get back to original data
}
}
This however does not work as it still alters the priority queue of the original algoObj.
I believe this is a beginner's question and stems from my lack of proper understanding when working with OO languages. Any help would be appreciated.
First of all, it is crucial to know that assigning an existing object to another variable does not create a copy of the original object:
MyObject a = new MyObject();
MyObject b = a; // does NOT create a copy!
// now a and b "point" to the same single instance of MyObject!
Some thoughts about your actual problem:
Your priority queue is just a working data structure that is used for the intersection algorithm, and just while the algorithm is running. When its done (so the intersection(s) have been found), it is empty or at least altered, as you already wrote. So the priority queue must be recreated for every algorithm run.
So what you should do:
Load the segments from the CSV file into your ArrayList, but don't pass it to the priority queue yet.
Refill (or recreate) the priority queue every time before calling findIntersection(). This is best be done by passing all segments to the method and creating a new prioerity queue from scratch:
public void findIntersection(Collection<Segment> segments) {
PriorityQueue<Segment> pQueue = new PrioerityQueue<Segment>(segments);
while (!pQueue.isEmpty()) {
p.poll(); //removes element from Queue
// do something
}
}
Hint: As I've already wrote at the beginning, this does not copy the individual segments nor the segment collection. It just passes a references. Of course, the priority queue will have to create internal structures at construction time, so if the segments collection is huge, this may take some time.
If this solution is too slow for your needs, you will have to work on your algorithms. Do you really need to check for intersections so often? If you add just one segment to the list, it should be sufficient to check intersections with the other segments, but not if the other segments intersect each other. Probably you could store your segments in a binary search tree similar to the one used by the Bentley–Ottmann algorithm. Whenever a new segment "arrives", it can be checked against the search tree, which should be doable with a time complexity of about O(log n). After that, the segment can be inserted into the tree, if necessary.
Or maybe you can add all segments first and then check for intersections just once.

Inserting into a Priority queue

I've been given a task of making a priority queue from scratch without extension programs.
The underlying task in hand is to create a priority queue for an IT ticketing System that allows the IT workers to prioritize which tasks within the company must be completed first . (priority = 1 -> Highest priority and 4 being the lowest).
I'm attempting to do this via a singly linked list.
My issue in hand is once my insertInQueue(Ticket T) function takes the last value in it fails.
The failure return statement is
Exception in thread "main" java.lang.NullPointerException
at Queue.insertInQueue(Queue.java:36)
(the line of code at line 36):
`if( temp.getNextTicket().getPriority() > T.getPriority())
at Main.main(Main.java:21) (The last object to go into the system)
private Ticket head;
private Ticket tail;
public void insertInQueue(Ticket T){
Ticket temp = head;
if(head == null){ //When no values are in the queue
head = T; //head = Ticket
tail = T; //tail = Ticket
}else if(T.getNextTicket() == null){
tail.setNextTicket(T);
tail = T;
}
else{
while( temp != null ){
if( temp.getNextTicket().getPriority() > T.getPriority()){
T.setNextTicket(temp.getNextTicket());
temp.setNextTicket(T);
}
temp = temp.getNextTicket();
}
}
}
Example of input:
Ticket T8 = new Ticket(8, "Ben_DG", 4);
I've tried a few different things but havn't gotten anywhere. Would anybody be able to help me out?
If you need more of my code let me know and I'll post it up. (just a little concerned some class mates would steal it)
Thanks!
Since you haven't provided the rest of the code for what set and get next ticket, I can't tell for sure, but logically at some point you are trying to get a NULL value with your get method which is giving you the error. Check all your conditionals properly and see if you aren't trying to get a NULL value.
That should be the main issue and should fix it

Java - Two threads get into the same condition and pass

I am working on a BTree and I want to synchronize it but the problem is:
I don't want to synchronize the whole method because it has a complex functionality.
My question is: how can I prevent first two or three threads from passing the first condition which root==null?
public void add(TrackingDevice device) {
// Tree is Empty, then add a new elemet to root
if (root == null ) {
root = new BTreeNode(true);
root.keys[0] = device;
root.n++;
} else {
/*
* The root is Full
*/
if (root.n == 2 * t - 1) {
splitRoot();
root.insert(device);
height++;
} else {
root.insert(device);
}
}
}
I would use an AtomicReference with its compareAndSet method.
Then more than one thread may pass the condition root.get() == null and create the root node. But only the fastest thread will write the value via compareAndSet.
I am just suggesting: implement a semaphore-like structure. Define a synchronized counter which your Threads will decrement each time they enter (be careful: this operation must be mutual exclusive) and prevent Threads from entering a section if counter == 0.
You could use an AtomicReference<BTreeNode> for the reference to the root node and use compareAndSet(null, new BTreeNode(true)) to guard entrance to the if block. If the add method is called very frequently this approach ends up creating many short lived BTreeNode instances though. If this is a concern, you can check "manually" first whether the AtomicReference contains null and only if so call compareAndSet.
However, I would get rid of the null check entirely and initially set a root node with n = 0. This makes the code more uniform as then there is no need for checking whether the root exists.

Data Structures in 2D-Games with Multiplayer (Java)

I have following problem:
I've programmed a 2D Game with a multiplayer function. Right now i store others Player Data and GameObjects in two ArrayList (The world is stored otherwise). Sometimes the Network-Thread sends Updates, which can not be applied, because the Game draws the Players/Game Objects (java.util.ConcurrentModificationException). Because this drawing process happens every Second around 60 times (because of animations) the problem apeers often (every 2 seconds). This is the code for the players ArrayList:
Draw the Players:
for (Player p : oPlayer) {
if (p != null) {
int x = (int) ((width / 2) + (p.x - getPlayerX()) * BLOCK_SIZE);
int y = (int) ((height / 2) + (p.y - getPlayerY()) * BLOCK_SIZE);
g.drawImage(onlinePlayer, x, y, BLOCK_SIZE, BLOCK_SIZE, null);
FontMetrics fm = g.getFontMetrics();
g.setColor(Color.DARK_GRAY);
g.drawString(p.getName(), x + (BLOCK_SIZE / 2) - (fm.stringWidth(p.getName()) / 2), y - 5);
}
}
Edit Information in Network-Thread:
case "ADP": //add Player
Game.oPlayer.add(new Player(message, id));
sendX();
sendY();
break;
case "SPX": // set X
for (Player p : Game.oPlayer) {
if (p.getId() == id) {
p.setX(Short.parseShort(message));
break;
}
}
break;
case "SPY": // set Y
for (Player p : Game.oPlayer) {
if (p.getId() == id) {
p.setY(Short.parseShort(message));
break;
}
}
break;
case "PDI": // remove Player
for (Player p : Game.oPlayer) {
if (p.getId() == id) {
Game.oPlayer.remove(p);
break;
}
}
break;
Thank you in advance :)
What happens here is, that 2 Threads are working on the same list.
The first one is reading the List (for (Player p : oPlayer) {) and the second one is modifying it (Game.oPlayer.add(new Player(message, id));). This brings the oPlayer list into an (sort of) "inconsistent" state. Java sees that you modified something that you are reading and throws this exception to let you know, that something is not kosher.
More information about ConcurrentModificationExceptions can be found here
To clarify, you dipped into the so called Readers-writer problem. You have an reader (Thread), that reads the Data of Game.oPlayer and a writer (Thread) that writes data to Game.oPlayer.
Solutions
Synchronized-Keyword
The synchronized keyword is explained here. You would use it like this:
private final List<Player> players = ...;
public void addPlayer(Player player) {
synchronized(players) {
players.add(player);
}
}
public void removePlayer(Player player) {
synchronized(players) {
players.remove(player);
}
}
Note that the List has to bee final. Furhter i am using a local attribute instead of your static one. Remove players with Game.oPlayer to get a suited solution.
This allows only 1 thread to access players.add() and players.remove().
Lock
Informations about how to use Locks can be found here.
Easy said, you create a block like this:
try {
lock.lock();
// work ..
} finally {
lock.unlock();
}
so that only one thread can access the work part by saying lock.lock(). If any other thread locked the work part using lock.lock() and not unlocked it, the current thread will wait until lock.unlock() is called. The try-finall block is used, to assure, that the lock is unlocked, even if your work part is throwing an throwable.
Furhter i would recommend itterating over a "copy" of the player-list like this:
List<Player> toIterate;
synchronized(players) {
toIterate = new ArrayList<>(getPlayerList());
}
for(Player player : toIterate) {
// work
}
Or synchronizing this part completly like this:
synchronized(players) {
for(Player player : players) {
// work
}
}
The first one provides you with an copy of that instance, which basically means, it contains the same Objects as the original List, but it isn't the same List. It helps you by letting more threads work on there own "list" and finish theire jobs, regardless of updates at the current time, becaus the second example will block if:
Any thread wants to read the list.
Any thread modifies the list.
So you only have to synchronize the coppy part in the first example.
Even furhter (not particually part of your question, but still something that would make it easyer) i would recommend not using static, as you stated in Game.oPlayer.[...] and taking a look at Dependency Injection.
You could modify your Game-class to provide the methods addPlayer(Player player);, removePlayer(Player player); and getPlayerList(); to realy code in an Object Oriented fashion.
With that design, you could easyly modify your code, to handle the new concurrency issue.
If a list is iterated or modified in one thread and also in another thread you will get a ConcurrentModficationException. In general user interface applications restrict modifying model data to a single thread, usually the user interface thread, such as the event dispatch thread of Swing, or the platform thread in JavaFX.
As an aside, for JavaFX there exists a game library providing out of the box techniques for game development. JavaFX in general is much better suited for graphics intensive work than AWT or Swing.
Have you tried using Vector instead? It is part of Collection and is synchronized.

In Java how do I change the length of a ArrayBlockedQueue?

I'm creating a media player app for Android. I have two threads: one producing audio frames, and another consuming those frames.
I want my customer to be able to experiment with using different sizes of ArrayBlockedQueue's, from "no" buffering (really 1) to up to 10 blocks of buffering.
I can't seem to find any classes in Java that provide a similar functionality to ArrayBlockedQueue, but allows me to dynamically make the list of items longer/shorter.
Question 1) Does anyone know of a class that functions similar to ArrayBlockedQueue, yet allows me to change the amount of items to hold?
Then I had a strange thought: Could I fudge it? Could I create a new ArrayBlockedQueue with the new size, and step through copying the 1-10 items that are currently in the old ArrayBlockedQueue and putting them into the new ArrayBlockedQueue, and then storing a pointer to the new ArrayBlockedQueue over the old one?
Since there'll never be more than 10 (or whatever my buffer limit is), it shouldn't take too much time copying the items to the new array.
Question 2) Is that a "reasonable" way to approach an ArrayBlockedQueue implementation that still gives me flexibility?
Question 3)Is there a better way to approach this?
-Ken
You will probably need to create your own BlockingQueue implementation that wraps your old queue and the new queue - poll from the old queue until it's empty, then set it to null to prevent any memory leaks. This way you won't lose any pending puts on the old queue
MyBlockingQueue {
private MyBlockingQueue oldQueue
private ArrayBlockingQueue newQueue
ArrayBlockingQueue(int newCapacity, MyBlockingQueue _oldQueue) {
oldQueue = _oldQueue
newQueue = new ArrayBlockingQueue(newCapacity)
E oldVal = null
while(newQueue.remainingCapacity() > 0 &&
(oldVal = oldPoll) != null)
newQueue.put(oldVal)
}
boolean isEmpty() {
(oldQueue == null || oldQueue.isEmpty) && newQueue.isEmpty
}
void put(E e) {
newQueue.put(e)
}
E take() {
E oldVal = oldPoll
if(oldVal != null) oldVal else newQueue.take
}
E poll() {
E oldVal = oldPoll
if(oldVal != null) oldVal else newQueue.poll
}
private E oldPoll() {
// If you have more than one consumer thread, then use a temporary variable
// for oldQueue - otherwise it might be set to null between the null check
// and the call to poll
if(oldQueue == null) null
else {
E oldVal = oldQueue.poll
if(oldVal != null) oldVal
else {
oldQueue = null
null
}
}
}
}
To your questions:
1) There isn't one that allows you to manually change the queue size, although something like a LinkedBlockingQueue will grow up to the max that you set for it.
2 and 3) You could do what you described (create a new ArrayBlockingQueue) using the 3rd constructor described in the docs:
ArrayBlockingQueue(int capacity, boolean fair, Collection c)
Creates an ArrayBlockingQueue with the given (fixed) capacity, the specified access policy and initially containing the elements of the given collection, added in traversal order of the collection's iterator.
This gives you the copy construction that you're looking for, and allows you to set the new capacity. Sizing up:
// create the first queue
Queue smallQueue = new ArrayBlockingQueue(5);
// copy small queue over to big queue
Queue bigQueue = new ArrayBlockingQueue(10, false, smallQueue);
Sizing down (pseudocode):
Queue bigQueue = new ArrayBlockingQueue(10);
// start processing data with your producer / consumer.
// then...
Queue smallQueue = new ArrayBlockingQueue(1);
// 1) change producer to start doing puts into the smallQueue
// 2) let consumer continue consuming from the bigQueue until it is empty
// 3) change consumer to start polling from the smallQueue
Your puts from step 1 will block until you switch the consumer over.

Categories

Resources