Unable to add to object ArrayList from other class [closed] - java

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I got a concurrent modification exception from adding an element to an ArrayList located in another class. (GUI program)
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891)
at sentinel/entity.EntityManager.tick(EntityManager.java:35)
at sentinel/worlds.World.tick(World.java:80)
at sentinel/state.GameState.tick(GameState.java:25)
at sentinel/game.Game.tick(Game.java:72)
at sentinel/game.Game.run(Game.java:115)
at java.base/java.lang.Thread.run(Thread.java:844)
I tried to include an iterator because I googled how to resolve the ConcurrentModificationException. However, it did not help or maybe I am using it wrong.
This is the class that I am adding the element to the ArrayList.
public class SentryHive extends StaticEntity{
private long lastSpawnTimer, spawnCooldown = 1000, spawnTimer = spawnCooldown;
private Random r = new Random();
public SentryHive(Handler handler, double x, double y) {
super(handler, x, y, tiles.Tiles.TILEWIDTH*3, tiles.Tiles.TILEHEIGHT*3);
bounds.x = 32*3;
bounds.y = 64*4 - 80;
bounds.width = 50;
bounds.height = 32;
}
#Override
public void tick() {
SpawnSentry();
}
public void SpawnSentry() {
spawnCooldown = r.nextInt(100) * 1000;
spawnTimer += System.currentTimeMillis() - lastSpawnTimer;
lastSpawnTimer = System.currentTimeMillis();
//Iterator<Entity> it = handler.getWorld().getEntityManager().getEntities().iterator();
//while (it.hasNext()) {
if(spawnTimer >= spawnCooldown) {
handler.getWorld().getEntityManager().addEntity(new Sentry(handler, 1080, 910, 10, 10));
}
// }
spawnTimer = 0;
}
this is the part of my program where I added other entities (if you need):
public class World {
private int width, height;
private int[][] tiles;
private int[][] entities;
private int spawnx, spawny;
private Handler handler;
private EntityManager entityManager;
private State state;
private ItemManager itemManager;
public int requiredSentry = 0;
private Random r = new Random();
//fun: ALT command R to change all of the same word in a file
public World(Handler handler, String path, String topper) {
this.handler = handler;
entityManager = new EntityManager(handler, new Player(handler, 600, 600));
itemManager = new ItemManager(handler);
entityManager.addEntity(new SentryHive(handler, 980, 810));
loadWorld(path);
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
int temp = r.nextInt(1000);
if(temp >=1 && temp <= 10) {
entityManager.addEntity(new DyingTree(handler, i*64, j*64));
} else if(temp >= 11 && temp <= 15) {
entityManager.addEntity(new Sentry(handler, i*64, j*64, 10, 10));
} else if(temp >= 21 && temp <= 25) {
entityManager.addEntity(new Beetle(handler, i*64, j*64, 40, 40));
} else if(temp == 30) {
entityManager.addEntity(new BeetleRed(handler, i*64, j*64, 40, 40));
}
}
}
entityManager.getPlayer().setX(spawnx * Tiles.TILEWIDTH);
entityManager.getPlayer().setY(spawny * Tiles.TILEHEIGHT);
}
below is my entity manager class (if you need):
public class EntityManager {
private Handler handler;
private Player player;
private ArrayList<Entity> entities;
private Comparator<Entity> renderSorter = new Comparator<Entity>() {
#Override
public int compare(Entity a, Entity b) {
if(a.getY() + a.getHeight() < b.getY() + b.getHeight())
return -1;
return 1;
}
};
public EntityManager(Handler handler, Player player) {
this.handler = handler;
this.player = player;
entities = new ArrayList<Entity>();
addEntity(player);
}
public void tick() {
Iterator<Entity> it = entities.iterator();
while(it.hasNext()) {
Entity e = it.next();
e.tick();
if(!e.isActive())
it.remove();
}
entities.sort(renderSorter);
}
public void addEntity(Entity e) {
entities.add(e);
}
I think there might be an initialization or declaration error somewhere, I just want the list to add the entity and resolve the error because my render method can draw everything in the ArrayList to the screen.

Your list is used by multiple thread and at same time if one thread try to read and another try to write then this Exception will Occur, to avoid this you can used CopyOnWriteArrayList list .
Example:
CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();
Write data using this is more costlier , so read all pros and cons of this api.

Related

Put class method into ThreadPoolExecutor in Java

I am new to Java and multithreading too. I've read about ThreadPool and saw that I can submit/execute lambda functions into ThreadPoolExecutor for example. But how can I do it for class methods in Java?
public class ParallelPointSystem{
private ArrayList<Cluster> clusters;
private ArrayList<Point> points;
private int dimension;
private int clusters_amount;
private int iterations;
private void attach_point(int i) throws Exception {
double distance = Point.get_distance(this.points.get(i), this.clusters.get(0).get_current_center());
int ind = 0;
for(int j = 1; j < clusters_amount; j++){
double dst = Point.get_distance(this.points.get(i), this.clusters.get(j).get_current_center());
if(distance > dst){
distance = dst;
ind = j;
}
}
this.clusters.get(ind).attach(this.points.get(i));
}
}
I tried to wrap a method in a class that implements the Runnable interface, but is this the only way to do that? Am I doing it right?
class Attach_Point implements Runnable{
private int i;
private ArrayList<Cluster> clusters;
private ArrayList<Point> points;
private int clusters_amount;
public Attach_Point(int i, ArrayList<Cluster> clusters, ArrayList<Point> points, int cluster_amount){
this.i = i;
this.clusters = clusters;
this.points = points;
this.clusters_amount = cluster_amount;
}
#Override
public void run(){
double distance = Point.get_distance(this.points.get(i), this.clusters.get(0).get_current_center());
int ind = 0;
for(int j = 1; j < clusters_amount; j++){
double dst = Point.get_distance(this.points.get(i), this.clusters.get(j).get_current_center());
if(distance > dst){
distance = dst;
ind = j;
}
}
try {
this.clusters.get(ind).attach(this.points.get(i));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
You don't actually need to implement Runnable. You only need to make sure to define a method on your class that matches the signature of public void run() and pass either lambda or method reference for your task.
For example this works:
class MyClass {
public void doIt() {
System.out.println("Hello "+this+" in "+Thread.currentThread());
}
}
Example calls submitting above task:
ExecutorService pool = Executors.newFixedThreadPool(1);
// Submit as method reference:
pool.execute(new MyClass()::doIt);
MyClass obj = new MyClass();
// Submit as Runnable lambda:
pool.execute(() -> obj.doIt());
Obviously if you had MyClass implements Runnable and a run() method, simply use:
pool.execute(obj);

Bowling Game Program - Assertion Error

I am in the somewhat beginning stages of creating a bowling program in Java. I currently have a JUnit test file called BowlingGameTest and a Java class called Game...both of these are under my Java project, BowlingGame. I have the following code in my BowlingGameTest file:
import junit.framework.TestCase;
public class BowlingGameTest extends TestCase {
private Game g;
protected void setUp() throws Exception {
g = new Game();
}
private void rollMany (int n, int pins) {
for (int i = 0; i < n; i++) {
g.roll(pins);
}
}
public void testGutterGame() throws Exception {
rollMany(20,0);
assertEquals(0, g.score());
}
public void testAllOnes() throws Exception {
rollMany(20,1);
assertEquals(20, g.score());
}
public void testOneSpare() throws Exception {
rollSpare();
g.roll(3);
rollMany(17,0);
assertEquals(16,g.score());
}
public void testOneStrike() throws Exception {
g.roll(10); //strike
g.roll(3);
g.roll(4);
rollMany(16,0);
assertEquals(24, g.score());
}
private void rollSpare() {
g.roll(5);
g.roll(5);
}
}
and the following code in my Java class, Game:
public class Game {
private int rolls[] = new int[21];
private int currentRoll = 0;
public void roll(int pins) {
rolls[currentRoll++] = pins;
}
public int score() {
int score = 0;
int frameIndex = 0;
for (int frame = 0; frame < 10; frame++) {
if (rolls[frameIndex] == 10) //strike
{
score += 10 +
rolls[frameIndex + 1] +
rolls[frameIndex + 2];
frameIndex++;
}
else if (isSpare(frameIndex))
{
score += 10 + rolls[frameIndex + 2];
frameIndex += 2;
} else {
score += rolls[frameIndex] +
rolls[frameIndex+1];
frameIndex += 2;
}
}
return score;
}
private boolean isSpare(int frameIndex) {
return rolls[frameIndex] +
rolls[frameIndex + 1] == 10;
}
}
I keep getting 2 errors when testing my program:
How can I fix this? I know I can simply change the numbers in my assertEquals code, but I am wanting those numbers, 16 and 24.

Java Object Array Initialization

I am working on a java project which contains 3 classes and an object array in one of the classes. This project is ultimately supposed to move 4 entity objects around on a board by using the coordinates of the entity objects. These entity objects are stored in an array in the world class. My problem is with the array initialization in the world class. I am not sure how to set each element of the array equal to an object from the entity class and then access that object's coordinates to move it around on the board. The coordinates for the entity objects are initially set at 20x30 in a default constructor. Here is my code:
public class entity {
private int xcoordinate;
private int ycoordinate;
private String name;
private char symbol;
public entity(){
xcoordinate = 20;
ycoordinate = 30;
}
private entity(int newxcoor, int newycoor, String newname, char newsymbol){
xcoordinate = newxcoor;
ycoordinate = newycoor;
name = newname;
symbol = newsymbol;
}
public int getXCoor(){
return xcoordinate;
}
public int getYCoor(){
return ycoordinate;
}
}
public class world {
private entity[] ObArray = new entity[4];
public world(){
world test = new world();
}
public void draw(){
for (int i = 0; i < 4; i++)
{
//int x = ObArray[i].getXLoc();
//int y = ObArray[i].getYLoc();
}
}
}
public class mainclass {
public static void main(String[] args){
world worldob = new world();
//entity a = new entity();
//entity b = new entity();
//entity c = new entity();
//entity d = new entity();
worldob.draw();
}
}
My draw function and main function are not finished. After the array is initialized I will be able to finish the draw method using the entity get functions.
Thanks for your help.
That is one way of doing it. You can also define all of your entities inline like this:
private entity[] ObArray = {
new entity(0,0,"Entity1",'a'),
new entity(10,10,"Entity2",'b'),
new entity(20,20,"Entity3",'c'),
new entity(30,30,"Entity4",'d')
};
A better way may be to do an ArrayList instead of an array:
private List<entity> ObArray = new ArrayList<>();
ObArray.add(new entity(0,0,"Entity1",'a');
ObArray.add(new entity(10,10,"Entity2",'b');
ObArray.add(new entity(20,20,"Entity3",'c');
ObArray.add(new entity(30,30,"Entity4",'d');
To access each element you just need to get the element from the array and either get or set the properties you need:
ObArray[0].getXCoor();
ObArray[0].setXCoor(5);
Your problem is only creating new object of world inside world's constructor which throws stack overflow error, otherwise it is fine:
public world(){ world test = new world(); //REMOVE THIS LINE
}
You simply need to initialise the array. This can be done in the world constructor.
public world()
{
for (int i = 0; i < 4; i++)
{
ObArray[i] = new entity();
}
}
Then you can access the objects in your draw method, as you've shown:
public void draw()
{
for (int i = 0; i < 4; i++)
{
int x = ObArray[i].getXCoor();
int y = ObArray[i].getYCoor();
System.out.println("x" + x);
System.out.println("y" + y);
// Manipulate items in the array
// ObArray[i].setXCoor(10);
}
}
A more complete example, with the move functions added, and the class names capitalised:
public class Entity
{
private int xcoordinate;
private int ycoordinate;
private String name;
private char symbol;
public Entity()
{
xcoordinate = 20;
ycoordinate = 30;
}
private Entity(int newxcoor, int newycoor, String newname, char newsymbol)
{
xcoordinate = newxcoor;
ycoordinate = newycoor;
name = newname;
symbol = newsymbol;
}
public int getXCoor()
{
return xcoordinate;
}
public void setXCoor(int xcoordinate)
{
this.xcoordinate = xcoordinate;
}
public int getYCoor()
{
return ycoordinate;
}
public void setYcoor(int ycoordinate)
{
this.ycoordinate = ycoordinate;
}
public static void main(String[] args)
{
World worldob = new World();
worldob.draw();
worldob.move(0, 15, 30);
worldob.move(1, 45, 0);
worldob.move(2, 23, 27);
worldob.move(3, 72, 80);
worldob.draw();
}
}
class World
{
private final Entity[] ObArray;
public World()
{
this.ObArray = new Entity[4];
for (int i = 0; i < ObArray.length; i++)
{
ObArray[i] = new Entity();
}
}
public void move(int index, int xCoor, int yCoor)
{
if (index >= 0 && index < ObArray.length)
{
Entity e = ObArray[index];
e.setXCoor(xCoor);
e.setYcoor(yCoor);
}
}
public void draw()
{
for (Entity e : ObArray)
{
int x = e.getXCoor();
int y = e.getYCoor();
System.out.println("x" + x);
System.out.println("y" + y);
}
}
}

Java performing instance commands before static ones [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I ran into this problem, when an object uses a classes static instance, before it's even created. Example:
class Chair {
public static Chair mychair = new Chair();
public void foo() {}
}
class Table {
public Table() {
Chair.mychair.foo();
}
}
So if I call the mychair.foo() , I get a NullPointerException. I know, not even static things get performed until the class is really needed. But how can I force Java to actually load the class, so it will be created?
Stacktrace of original program:
Exception in thread "main" java.lang.ExceptionInInitializerError
at hu.intelligames.game.level.Level.<init>(Level.java:34)
at hu.intelligames.game.Game.initialize(Game.java:64)
at hu.intelligames.game.Game.<init>(Game.java:43)
at hu.intelligames.game.Game.main(Game.java:80)
Caused by: java.lang.NullPointerException
at hu.intelligames.game.level.tiles.Tile.<clinit>(Tile.java:25)
... 4 more
Constructor of Level class (from line 25):
public Level(int width, int height) {
this.width = width;
this.height = height;
tiles = new Tile[width * height];
for (int i = 0; i < tiles.length; i++) {
if (i % 3 == 0)
tiles[i] = Tile.GRASS;
else if (i % 3 == 1)
tiles[i] = Tile.GRASS;
else
tiles[i] = Tile.STONE;
}
init();
}
Whole code for Tile class:
public class Tile {
public static Spritesheet tileSheet = new Spritesheet("/tiles.png");
public static final Tile VOID = new Tile(0, 0, tileSheet, 0x00000000);
public static final Tile GRASS = new Tile(1, 0, tileSheet, 0xff00ff00);
public static final Tile STONE = new Tile(2, 0, tileSheet, 0xffaaaaaa);
public static final Tile ROAD = new Tile(3, 0, tileSheet, 0xffabcdef);
private Spritesheet sheet;
private int x;
private int y;
private int colorCode;
private static ArrayList<Tile> tileList;
static {
tileList.add(VOID);
tileList.add(GRASS);
tileList.add(STONE);
tileList.add(ROAD);
}
public Tile(int x, int y, Spritesheet sheet, int colorCode) {
this.sheet = sheet;
this.x = x;
this.y = y;
this.colorCode = colorCode;
}
public void render(int xPos, int yPos, int xOff, int yOff, Screen screen) {
screen.render(xPos, yPos, xOff, yOff, x, y, sheet);
}
public int getColorCode() {
return colorCode;
}
public static Tile getTileByColorCode(int code) {
for (Tile t : tileList) {
if (t.getColorCode() == code) return t;
break;
}
return VOID;
}
}
private static ArrayList<Tile> tileList;
Remains null
static {
tileList = new ArrayList<>();
tileList.add(VOID);
tileList.add(GRASS);
tileList.add(STONE);
tileList.add(ROAD);
}
Your field tileList is not initialized, so the static initialization code throws NPE.
This should do the trick:
private static ArrayList<Tile> tileList = new ArrayList<>();

Java - Multithreads immutable object

I have this class:
class S2Es2SharedState {
public int x;
public int y;
}
that is used to share an s2Es2SharedState object in every thread inside in the loop:
class S2Es2Worker implements Runnable {
private final int id;
private S2Es2SharedState state;
private final int delay;
private int numErrors = 0;
public S2Es2Worker(final int id, final S2Es2SharedState state,
final int delay) {
this.state = state;
this.delay = delay;
this.id = id;
this.numErrors = 0;
System.out.println("Worker " + id + ": created with " + delay
+ " ms delay");
}
#Override
public void run() {
boolean check = true;
System.out.println("Worker " + id + ": started");
for (int i = 0; i < 150; i++) {
state.x++;
try {
Thread.sleep(delay);
} catch (final InterruptedException e) {
// do nothing
}
state.y++;
}
}
}
in this program working 10 threads where each of them enter in the loop and increment 150 times the value of x and y of the shared object, so the final result in the x and y of the shared object is 1500.If i don't change anything this program have a problem of race condition, so for fix this problem i used the lock (and it works). But now i want to fix the problem of the race condition using the immutable object instead of the locks. so i changed the class of the shared object in this way:
final class S2Es2SharedState {
private final int x;
private final int y;
public S2Es2SharedState(final int x, final int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public S2Es2SharedState incrementX() {
return new S2Es2SharedState(x+1, y);
}
public S2Es2SharedState incrementY() {
return new S2Es2SharedState(x, y+1);
}
}
and in the run() method i changed the state variable in this way:
class S2Es2Worker implements Runnable {
....
private volatile S2Es2SharedState state;
....
and in the for loop i did this edit:
for (int i = 0; i < 150; i++) {
state = state.incrementX();
try {
Thread.sleep(delay);
} catch (final InterruptedException e) {
// do nothing
}
state = state.incrementY();
}
}
But i don't know why the final result is that the shared object has instead of x=1500 and y=1500 150 in both variableHow can i fix the problem with the race of condition using the immutable object?
I'm going to assume you create a S2Es2SharedState (use simpler names for asking questions) as
S2Es2SharedState state = new S2Es2SharedState(0, 0)
and passing it to the S2Es2Worker instances something like
for (int i = 0; i < 10;i++) {
S2Es2Worker worker = new S2Es2Worker(i, state, 5);
new Thread(worker).start();
}
In java, everything is passed by value. So the using state as a method argument, a copy of the value of the reference is passed.
So the field
private volatile S2Es2SharedState state;
is also referencing the same object. However, if you change the reference that the field state is holding, for example with
state = state.incrementX();
that doesn't affect any other references.

Categories

Resources