i have just attempted to add something to my game where if one player is hit by a bullet his health goes down. problem is when i am checking for this, CPU is at 100% and everything sooo laggy. This is a problem. here is the thread i am using:
package Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
public class BulletCollision implements Runnable {
Player1 player1 = new Player1();
Player2 player2 = new Player2();
public Thread checkBulletCollision = new Thread(this);
public void checkPlayerBulletCollide() {
if (player2.getBulletX() > player1.getX() &&
player2.getBulletX() < player1.getX() - 50) {
player2.decHealth(50);
}
}
#Override
public void run() {
while(true) {
checkPlayerBulletCollide();
try {
checkBulletCollision.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(BulletCollision.class.getName()).log(
Level.SEVERE, null, ex);
}
}
}
}
i am pretty sure this is where the problem is. there are no errors when compiled or ran. if anyone could help that would be amazing! and i just make this class so the code is not perfect. i have tried a lot to fix this, the Threads start() method is being called in my Display class which only displays the JFrame. i previously had the start method in one of my player classed.
The problem is not in this code. There are one or two flaws, but nothing in this code that would result in laggyness ... as far as I can tell.
FWIW, the flaws are as follows:
1) This is bad style:
checkBulletCollision.sleep(100);
The Thread.sleep method is static, so you should invoke it as:
Thread.sleep(100);
2) Your thread run() method should return if it receives an interrupt. You have coded it to keep going ... which would defeat the purpose of interrupting it.
In my opinion, using this block free running in a separate thread is not correct in this case.
while(true) {
checkPlayerBulletCollide();
try {
checkBulletCollision.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(BulletCollision.class.getName()).log(Level.SEVERE, null, ex);
}
}
I'd only do this once each frame, I'd call the checkPlayerBulletCollide() from the drawing logic.
Also note that Thread.sleep() is a static function, so you can't make a specific Thread instance sleep from another Thread, a Threac can just put itself to sleep...
EDIT If you would like to code nice and clean (which is very good), I'd advise using the locking mechanisms we have from Java 1.5 on.
Even though this is (in the current context of 2 users with 1 bullet each) not lightweight ebough, I'd use a BlockingQueue. The checking thread would have to issue a queue.take(), but the actual Integer value wouldn't matter (later on e.g. with more bullets or players, you could put objects in the queue that specify which bullets and which users to check...). The drawing logic - or the logic controlling the drawing would do queue.offer(0). The checking Thread would look like this:
public class BulletCollision implements Runnable{
Player1 player1 = new Player1();
Player2 player2 = new Player2();
public BlockingQueue<Integer> checkQueue = new LinkedBlockingQueue<Integer>();
public void checkPlayerBulletCollide() {
if(player2.getBulletX() > player1.getX() && player2.getBulletX() < player1.getX() -50) {
player2.decHealth(50);
}
}
#Override
public void run() {
while(true) {
try {
queue.take();
checkPlayerBulletCollide();
} catch (InterruptedException ex) {
Logger.getLogger(BulletCollision.class.getName()).log(Level.SEVERE, null, ex);
break; //I'd put this here. If we were interrupted, the hread should stop gracefully.
}
}
}
}
Also, when you're done with drawing a frame, you should issue a queue.offer(0);
Related
I'm working on a little game (bomberman), using javafx. Basically, I have players which can plant bomb. The bomb has a duration (1500ms before explosion, for example).
So, when my player plant a bomb, I start a thread in the bomb, using a Thread.sleep(ms), and right after I notify the player that the bomb has exploded.
Thing is, my player can drop his bomb then move... But when the bomb explodes, it notify the instance of the player with the coordinate when the bomb was planted...
For example, if my player is in [2;2], plant a bomb, then move to [2;4], then the bomb explodes, my player goes back to [2;2]...
Anyone knows how could I actualize the instance of player my bomb is pointing to ... ?
Here's a sample of code :
public class Player{
public void putBomb(){
listBomb.add(new Bomb(this));
}
public void refresh(){
System.out.println(xCoordinate+" "+yCoordinate);
}
}
public class Bomb{
public Bomb(Player p){
observer=p;
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1500);
notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public void sendNotification(){
observer.refresh();
}
}
As your question is JavaFX specific, the recommendations on how to do this vary from a non-GUI Java program (because JavaFX has in-built concurrency assistance and a single-threaded application programming model).
You don't need another thread, you can use a PauseTransition.
public class Bomb{
public Bomb(final Player player){
PauseTransition pause = new PauseTransition(Duration.seconds(1.5));
pause.setOnFinished(event -> player.refresh());
pause.play();
}
);
If for some reason you didn't wish to use a transition and you want to use your own threading, then you should look use JavaFX concurrency utilities such as Task.
If you didn't want to use a Task, then you can still create your own thread or runnable, but ensure that any callbacks are made using Platform.runLater(). For example:
public class Bomb{
public Bomb(final Player player){
new Thread(() -> {
try {
Thread.sleep(1500);
Platform.runLater(() -> player.refresh());
} catch (InterruptedException e) {}
}
}).start();
}
}
Of the different approaches, I recommend the PauseTransition over the others as then you don't need to deal with concurrency details such as threading, which are easy to get wrong.
Your run method calls [this.]notify() without being synchronized on this. I would expect it to always throw an IllegalMonitorStateException.
Also, it's almost always a mistake to call notify() without also setting some variable that other threads can examine. The problem with notify() is that it does not do anything at all unless some other thread happens to be in a wait() call for the same object. Without proper synchronization, you have no way to guarantee that that will be true.
There's only one right way to use wait() and notify(), and that's in a design pattern that Oracle calls a guarded block. https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
I am starting two thread one after the other.
The first thread is reading in a loop from input and the other one check some condition in a loop to
sent an interrupt to the other.
The problem is that any thread of the two I start first it doesnt let the other stop.
If i start reading in never runs the other thread until it finishes and if I start the other thread is checking the condition in the loop and it wont move forward in code until the condition is true and gets out of the loop.
What is the correct way to do it?
Sample code below:
Thread 1)
public class InterruptionThread extends Thread {
public void run() {
while (condition not true) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (condition true) {
do some work
return;
}
}
}
Thread 2)
public class ReadingThread extends Thread{
public void run() {
int input;
while (true) {
try {
input = stdInput.read();
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.print((char) input);
}
}
}
This sounds like you are not starting the threads in a correct manner.
Use the start() method to start threads, not the run() method (which doesn't actually start a thread).
new InterruptionThread().start();
new ReadingThread().start();
I think your problem is of producer consumer problem type.
So would suggest you to use BlockingQueue.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
Also instead of directly handling threads; it will be easy if you use Executor Framework; this way thread management will become pretty easy.
I have a process which should react on some events. So when playFromList() is called it plays some sound from soundpool. Then in a thread I set a flag and for 3,5 seconds it should not play any sounds.
What I got is: It plays sound and if than wait 3,5 seconds. If playFromList() is called 5 times in 3,5 seconds it still gets to SoundManager.playSound(listNr), and still is done in 17,5 seconds. And its not exactly what I wanted. I wanted method SoundManager.playSound(listNr) called only once.
public class Settings{
public static boolean flag = false;
}
public class Main{
public void playFromList(int listNr,int g){
if(!Settings.flag){
SoundManager.playSound(listNr);
if(g ==0){
mpVolume((float) 0.3);
t5sec.run();
}else{pauseMus();}
}
}
private Handler vijfSeconden = new Handler(){
public void handleMessage(Message msg){
mpVolume((float)0.8);
}
};
Thread t5sec = new Thread(){
public void run(){
if(Settings.flag == false){
Settings.flag = true;
try {
Thread.sleep(3500);
} catch (InterruptedException e) {
Settings.flag = false;
e.printStackTrace();
}
vijfSeconden.sendEmptyMessage(0);
Settings.flag = false;
}
}
};
}
There are few problems with the code. Probably most important thing that is strange is
t5sec.run(), in Java you you should use start method on the Thread object to start new Thread. As written it will execute in the calling thread.
Second problem is absolute lack of synchronization, one way to fix that, I guess, would be to use AtomicBoolean instead of boolean in Settings.flag
Another issue is that it is quite expensive to start new thread every time. It is a bit hard to tell from the description precisely what you want to do, but if my understanding is correct you should just do something like this:
if ( (System.currentTimeInMillis() - lastTimePlayed) < 3500) {
playSound();
lastTimePlayed = System.currentTimeInMillis();
}
that's it and no threads required. You might want to use AtomicInteger to hold lastTimePlayed value if you want your class to be thread safe.
I want to make a thread, which runs, computes something with the data i give it, and returns a few values, or an object. The thread is a part of a Swing GUI.
My question: How can I make a method that runs when I make the thread, and returns an object (or whatever I want it to return)?
My code:
private void nextTurn () {
// do something
if (turn == white) {
try {
Engine e = new Engine(); // Engine is implemented by runnable
e.start();
Move m = e.getBestMove (board);
// thread should work, next code should be excecuted immediately
}
catch (Exception e) {}
}
// end of Main class
}
This is the first time I am working with Threads, and I know you should avoid them if possible, but I need it this time for my GUI.
The info on the Oracle site on Threads did not help me out. I am able to make a program with multiple Threads that runs indefinately, but I can't make it work with functions.
Since this is with a Swing GUI, consider using a SwingWorker object which creates a background thread (all the code run in the doInBackground method), and then can return a final result and/or interim results. Information on how to use this is well documented in the tutorials here:
Concurrency in Swing
SwingWorkers have property change support and thus will allow listeners to observe its state (as a SwingWorker.StateValue) via a PropertyChangeListener. This is one way your program can determine that the thread has completed its processing, get the returned result and go from there.
On an unrelated note, this isn't in your production code is it?:
catch (Exception e) {}
If so, you will likely want to fix this as ignored exceptions can bite you in the tail big time.
e.g.,
if (turn == white) {
try {
final SwingWorker<Move, Void> mySwingWorker = new SwingWorker<Move, Void>() {
#Override
protected Move doInBackground() throws Exception {
Engine e = new Engine(); // Engine is implemented by runnable
e.start();
Move m = e.getBestMove(board);
return m;
}
};
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (StateValue.DONE == mySwingWorker.getState()) {
try {
Move m = mySwingWorker.get();
// TODO: insert code to run on the EDT after move determined
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
});
mySwingWorker.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
I suggest you use an ExecutorService. It allows you to create a thread pool, you can pass tasks to it and get the results later.
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
I'm having trouble with memory in a j2me application. (see another question)
I discovered that one class has a loop that doesn't stop until the application is closed. This loop is consuming all the memory available.
I didn't make this class so I don't know why things was done this way. So any suggestions are welcome.
Here is a simplified version of the class:
import java.util.TimerTask;
public class SomeClass extends TimerTask implements Runnable {
private boolean running = false;
private Thread thread;
public void invokeThread() {
running = true;
thread = new Thread(this);
thread.start();
}
public void run() {
while(running) {
try {
Thread.sleep(800);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
doSomeStuff();
}
}
private void doSomeStuff() {
// do some stuff that consumes my memory
}
public void dispose() {
running = false;
}
}
Another class calls SomeClass.invokeThread() and wait for some user response (this already spend some memory).
When the users ends inputting data this another class calls dispose() and the while loop doesn't stop, wait some minutes or try to navigate a bit more the application and you get an OutOfMemoryError.
Can you help me?
thanks
Try adding keyword volatile to the variable running:
private volatile boolean running = false;
This is done to ensure that your thread always uses master-copy of the variable, not the locally stored.
Without seeing what's going on inside of doSomeStuff() it's impossible to tell why the loop doesn't terminate. Obviously the routine is expecting that dispose() is eventually going to be called or that running will eventually be set to false manually. If the loop isn't terminating, then neither of these things are happening. You should examine the logic within doSomeStuff() to figure out why.