I try hard to find the problem in this Java code, but I can't find it - can you help me?
I hope the code I provide is enough, but I will post more if necessary.
Further I apologize, I didn't make a minimal example.
game.getGroupPlayers().list();
MoverThread[] playerThread = game.getPlayers();
System.out.println(playerThread.length);
for (int i = 0; i < playerThread.length; i++) {
try {
System.out.println(i + " -> " +playerThread[i].toString());
returnString += playerThread[i].toString() + "\n";
} catch(NullPointerException e) {
System.out.println("Problem at i = " + i);
e.printStackTrace();
}
game.getGroupPlayers().list();
}
sometimes gives me the following output:
java.lang.ThreadGroup[name=Players,maxpri=10]
Player-0: 113
Player-1: 277
Player-2: 0
3
0 -> Player-0: 113
1 -> Player-1: 277
Problem at i = 2
java.lang.NullPointerException
at Referee.goalFound(Referee.java:70)
at DebugTestReferee.goalFound(DebugTestReferee.java:42)
at Player.checkGoal(Player.java:61)
at Player.run(Player.java:94)
at java.lang.Thread.run(Thread.java:636)
java.lang.ThreadGroup[name=Players,maxpri=10]
Player-0: 113
Player-1: 277
Player-2: 0
[edit]
here's the source of getPlayers()
/*
* post returns the games players as an array
*/
public MoverThread[] getPlayers() {
synchronized(movers) {
MoverThread[] playerList = new MoverThread[players.activeCount()];
players.enumerate(playerList);
return playerList;
}
}
[edit]
here's how players is generated
private ThreadGroup movers;
private ThreadGroup players;
private ThreadGroup ghosts;
private Observer observer;
/*
* constructor
*/
public Game(Maze maze, Referee referee) {
this.maze = maze;
this.referee = referee;
threadList = new ArrayList<MoverThread>();
movers = new ThreadGroup("Movers");
players = new ThreadGroup(movers, "Players");
ghosts = new ThreadGroup(movers, "Ghosts");
observer = null;
}
[edit]
Here's how I call the method that generates the problem:
/*
* post checks if the players thread was interrupted - if not if hostfield pretends to be a goal the game gets stopped and referee is called to perform "goal-found-actions"
*/
private void checkGoal() {
if (!getThread().isInterrupted()) {
synchronized(getGame().getMovers()) {
if (!getThread().isInterrupted()) {
if (getHostField().isGoal()) {
Field goal = getHostField();
getGame().getReferee().goalFound(this, goal);
getGame().setGameOver();
}
}
}
}
}
and here's the whole goalFound()
/*
* post action to be performed if a player finds a goal
* print some information
*/
public void goalFound(Player player, Field at) {
//FIXME get the Bug!!!
String returnString = "Game over - player " + player.getName() + " found a goal on (" + at.getPos()[0] + ", " + at.getPos()[1] + ")!\n";
game.getGroupPlayers().list();
MoverThread[] playerThread = game.getPlayers();
System.out.println(playerThread.length);
for (int i = 0; i < playerThread.length; i++) {
try {
System.out.println(i + " -> " +playerThread[i].toString());
returnString += playerThread[i].toString() + "\n";
} catch(NullPointerException e) {
System.out.println("Problem at i = " + i);
e.printStackTrace();
}
}
game.getGroupPlayers().list();
returnString += game.mazeString();
System.out.println(returnString);
}
There isn't a nice way of enumerating the Threads of a ThreadGroup. It's a well known terrible design.
Between calling ThreadGroup.activeCount and ThreadGroup.enumerate(Thread[]), threads may have started or died. The best you can do is add a fudge factor the activeCount when allocating the array. If the returned value matches the array length, then you may have missed some and should repeat with a larger array size (probably a factor larger, rather than just adding a constant). When successful, you will need to trim your array appropriately (or treat it as such).
game.getPlayers(); is returning MoverThread[] with length 3, but the third one is null.
I found a solution - or maybe more a workaround...
Beside using ThreadGroups I store my threads in an ArrayList aswell (maybe a Vector would be even better, but I'm fine with the ArrayList).
I don't know why, but when I try to call all Threads in the ThreadGroup it often happens that some Threads are left out. However, with the ArrayList it works fine.
Would be interesting why ThreadGroups don't work as supposed and what we need them for in this case.
Related
When the code is ran the nested loop causes it to create occasional duplicate entries to the system, i have spent a while looking through this but still cant find what is causing this, would greatly appreciate any help?
for(int i = 0; i < subWorkItemElement.getChildNodes().getLength(); i++) {
Boolean test = false;
WorkItemCommon existingChild = null;
String summary = null;
if(subWorkItemElement.getChildNodes().item(i).getNodeName().equals("workitem")) {
// We know it's a work item - but is it in the existing list?
Element childWorkItem = (Element) subWorkItemElement.getChildNodes().item(i);
for(int j = 0; j < subWorkItemElement.getChildNodes().getLength(); j++) {
if(childWorkItem.getChildNodes().item(j) instanceof Element) {
if(((Element)childWorkItem.getChildNodes().item(j)).getNodeName().equals("details")) {
summary = ((Element) childWorkItem.getChildNodes().item(j)).getElementsByTagName("summary")
.item(0).getTextContent();
for(String k : userInfoHashMap.keySet()) {
summary = summary.replace("${" + k + "}", userInfoHashMap.get(k));
}
if(childHashTable.containsKey(summary)) {
test = true;
existingChild = childHashTable.get(summary);
IWorkItem workItem = existingChild.getWorkItem();
System.out.println("INFO: The task with summary \"" + summary + "\" already exists. Skipping creation.");
System.out.println("this task is work item: " + workItem.getId());
//either check the tasks in the xml for updated details and then modify the existing workitem
//or just modify the work item without checking for updates
makeChildTask(childWorkItem, existingChild, childHashTable, userInfoHashMap, workItemHashMap, rtc, false);
break;
}
}
}
}
if(!test) {
System.out.println("INFO: The task with summary " + summary + " does not currently exist. Creating.");
makeChildTask(childWorkItem, thisItem, childHashTable, userInfoHashMap, workItemHashMap, rtc, true);
} else makeFromExistingChildTask(childWorkItem, existingChild, userInfoHashMap, workItemHashMap, rtc);
}
}
You are possibly (not sure what makeChildTask() does) changing an XML structure while iterating through the children list. While not necessarily incorrect, this can mean you get entries inserted while you process the list. Since you call the subWorkItemElement.getChildNodes().getLength() each time instead of cache'ing it, this might result in the length changing in between the loop iterations.
parsed this xml in java code, but problem is that i want to calculate lost percentage will be calculated by adding the lostperc of both direction(upstream,downstream). Below is the Java Code So far What I have Done.
<RR cid="1460458819000" sid="92555" eod="0">
<RR1 direction="0" statStatus="1792" lostperc="1" />
<RR1 direction="1" statStatus="1792" lostperc="1" />
</RR>
InputStream inputStream = new FileInputStream(file);// here I put above Xml
List<AccedianWrapper> accedianWrappers =accedianResponse.getList();
for (AccedianWrapper accedianWrapper : accedianWrappers) {
String dir = accedianWrapper.getDirection();
if (dir.equals("0") || dir.equals("1")) {
System.out.println("direction " + dir);
lstPer = Integer.valueOf(accedianWrapper.getLostperc());
System.out.println(lstPer);
}
//
lstPer = Integer.valueOf(accedianWrapper.getLostperc());
//System.out.println(lstPer);
if (lstPer >= 1) {
if (!alrtCount.containsKey(lid)) {
alrtCount = Collections.singletonMap(lid, count);
} else {
int countn = alrtCount.get(lid);
alrtCount = Collections.singletonMap(lid, countn + 1);
if(countn > 4) {
System.out.println("get 5 times consecutive lost percentage");
alrtCount = Collections.singletonMap(lid, count);
}
}
System.out.println(alrtCount);
} else{
if (alrtCount.containsKey(lid)) {
alrtCount = Collections.singletonMap(lid, count);
}
}
}
From accedianResponse I get List Of accedianWrapper which Is POjo and Having Element of Xml,By Iterating Over AccedianWrapper i get LostPerc and Direction as well.But My Requirement is to Combine the Direction=0 and Direction=1 and Add the lostperc, currently i a getting Single row one by one in loop getting lostperc.
I am sorry if i written anything wrong .... please help me out.....
I have a java code that generates a request number based on the data received from database, and then updates the database for newly generated
synchronized (this.getClass()) {
counter++;
System.out.println(counter);
System.out.println("start " + System.identityHashCode(this));
certRequest
.setRequestNbr(generateRequestNumber(certInsuranceRequestAddRq
.getAccountInfo().getAccountNumberId()));
System.out.println("outside funcvtion"+certRequest.getRequestNbr());
reqId = Utils.getUniqueId();
certRequest.setRequestId(reqId);
System.out.println(reqId);
ItemIdInfo itemIdInfo = new ItemIdInfo();
itemIdInfo.setInsurerId(certRequest.getRequestId());
certRequest.setItemIdInfo(itemIdInfo);
dao.insert(certRequest);
addAccountRel();
counter++;
System.out.println(counter);
System.out.println("end");
}
the output for System.out.println() statements is `
1
start 27907101
com.csc.exceed.certificate.domain.CertRequest#a042cb
inside function request number66
outside funcvtion66
AF88172D-C8B0-4DCD-9AC6-12296EF8728D
2
end
3
start 21695531
com.csc.exceed.certificate.domain.CertRequest#f98690
inside function request number66
outside funcvtion66
F3200106-6033-4AEC-8DC3-B23FCD3CA380
4
end
In my case I get a call from two threads for this code.
If you observe both the threads run independently. However the data for request number is same in both the cases.
is it possible that before the database updation for first thread completes the second thread starts execution.
`
the code for generateRequestNumber() is as follows:
public String generateRequestNumber(String accNumber) throws Exception {
String requestNumber = null;
if (accNumber != null) {
String SQL_QUERY = "select CERTREQUEST.requestNbr from CertRequest as CERTREQUEST, "
+ "CertActObjRel as certActObjRel where certActObjRel.certificateObjkeyId=CERTREQUEST.requestId "
+ " and certActObjRel.certObjTypeCd=:certObjTypeCd "
+ " and certActObjRel.certAccountId=:accNumber ";
String[] parameterNames = { "certObjTypeCd", "accNumber" };
Object[] parameterVaues = new Object[] {
Constants.REQUEST_RELATION_CODE, accNumber };
List<?> resultSet = dao.executeNamedQuery(SQL_QUERY,
parameterNames, parameterVaues);
// List<?> resultSet = dao.retrieveTableData(SQL_QUERY);
if (resultSet != null && resultSet.size() > 0) {
requestNumber = (String) resultSet.get(0);
}
int maxRequestNumber = -1;
if (requestNumber != null && requestNumber.length() > 0) {
maxRequestNumber = maxValue(resultSet.toArray());
requestNumber = Integer.toString(maxRequestNumber + 1);
} else {
requestNumber = Integer.toString(1);
}
System.out.println("inside function request number"+requestNumber);
return requestNumber;
}
return null;
}
Databases allow multiple simultaneous connections, so unless you write your code properly you can mess up the data.
Since you only seem to require a unique growing integer, you can easily generate one safely inside the database with for example a sequence (if supported by the database). Databases not supporting sequences usually provide some other way (such as auto increment columns in MySQL).
This seems like a very strange problem. I'm stress testing my neo4j graph database, and so one of my tests requires creating a lot of users (in this specific test, 1000). So the code for that is as follows,
// Creates a n users and measures the time taken to add another
n = 1000;
tx = graphDb.beginTx();
try {
for(int i = 0; i < n; i++){
dataService.createUser(BigInteger.valueOf(i));
}
start = System.nanoTime();
dataService.createUser(BigInteger.valueOf(n));
end = System.nanoTime();
time = end - start;
System.out.println("The time taken for createUser with " + n + " users is " + time +" nanoseconds.");
tx.success();
}
finally
{
tx.finish();
}
And the code for dataService.createUser() is,
public User createUser(BigInteger identifier) throws ExistsException {
// Verify that user doesn't already exist.
if (this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER, identifier)
.getSingle() != null) {
throw new ExistsException("User with identifier '"
+ identifier.toString() + "' already exists.");
}
// Create new user.
final Node userNode = graphDb.createNode();
final User user = new UserWrapper(userNode);
user.setIdentifier(identifier);
userParent.getNode().createRelationshipTo(userNode, NodeRelationships.PARENT);
return user;
}
Now I need to call dataService.getUser() after I've made these Users. The code for getUser() is as follows,
public User getUser(BigInteger identifier) throws DoesNotExistException {
// Search for the user.
Node userNode = this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER,
identifier).getSingle();
// Return the wrapped user, if found.
if (userNode != null) {
return new UserWrapper(userNode);
} else {
throw new DoesNotExistException("User with identifier '"
+ identifier.toString() + "' was not found.");
}
}
So everything is going fine until I create the 129th user. I'm following along in the debugger and watching the value of dataService.getUser(BigInteger.valueOf(1)) which is the second node, dataService.getUser(BigInteger.valueOf(127)) which is the 128th node, and dataService.getUser(BigInteger.valueOf(i-1)) which is the last node created. And the debugger is telling me that after node 128 is created, node 129 and above aren't created because getUser() throws a DoesNotExistException for those nodes, but still gives values for node 2 and node 128.
The user id I'm passing to createUser() is autoindexed.
Any idea why it isn't making more nodes (or not indexing these nodes)?
It sounds suspiciously like a byte value conversion which flips around at 128. Could you make sure there isn't anything like that going on in your code?
I have this code. And basically this returns the correct data without the town qualities. When I add the town qualities the method returns nothing, not even the orginal data that it has been and I dont know why. Can anyone see a problem?
protected void listRecords() {
mListForm.deleteAll(); // clear the form
try {
RecordStore rs = RecordStore.openRecordStore("Details", true);
RecordEnumeration re = rs.enumerateRecords(null, new RecordSorter(), false);
while (re.hasNextElement()) {
byte [] recordBuffer = re.nextRecord();
String record = new String(recordBuffer);
// extract the name and the age from the record
int endOfName = record.indexOf(";");
int endOfDesc = record.indexOf(";" , endOfName + 1);
int endOfTown = record.indexOf (";", endOfDesc + 1);
String name = record.substring(0, endOfName);
String desc = record.substring(endOfName + 1, endOfDesc);
String town = record.substring(endOfDesc +1, endOfTown);
mListForm.append(name + " aged: "+ desc + " " + town);
}
rs.closeRecordStore();
}
catch(Exception e){
mAlertConfirmDetailsSaved.setString("Couldn't read details");
System.err.println("Error accessing database");
}
mDisplay.setCurrent(mListForm);
}
Have you tried running it in the debugger? Is the exception happening? Are the three semicolons present in the record? Is there a limit on mDisplay's string size? When setCurrent is called, is the mListForm correct?
In other words, what have you done so far and where is it definitely right, and where does it become wrong?