Solved

Thread problem is ruining my life

Posted on 1998-02-08
11
196 Views
Last Modified: 2010-04-16
If you can solve my problem then, in addition to points, you will have my eternal gratitude.
I am designing an applet which features moving graphics.
There is to be a "GameManager" class which will periodically
move all of the graphical objects according to their own
methods(I have this part down & it works).  The problem is
that the GameManager is supposed to dynamically alter the
behavior of the graphical object according to user input
(Mouse click events).  I have been unable to find a way to interrupt my infinite "move and wait" loop in such a way as to allow mouse clicks to be collected and processed in between moves. I am right now using the VisualAge for Java VM (not that it matters, since all VM's implementations are the same-right;-)?)  Anyway, the code I have looks something like this, to give you an idea:

Class GameScreen{
GameMangager gameManager;
...
...
public boolean handleEvent(Event evt ) {
// I am using this because I want my applet to be
// able to run on 1.02 browsers
if (evt.id      == Event.MOUSE_DOWN) {
              gameManager.processEvent(evt.x, evt.y);
      }
            return super.handleEvent(evt);
}      
public class GameManager implements Runnable{
Thread t;
...
...
public void processEvent{
...
...
}
private void move{
//contains all of the gory details
//of how to calculate movement of
//graphical objeces
...
...
}

public void run{
while(true){ //Infinite loop
move();
//[NEED METHOD HERE TO YIELD CONTROL UNTIL NEXT MOVEMENT
//SO THAT THE VM CAN PROCESS THE MOUSE CLICKS ANT INFORM
//THIS CLASS OF THEM.  EXPEREMENTING WITH A VERY LONG FOR
//LOOP HAS REVEALED THAT THE CLICKS ARE IN FACT NOTED, BUT
//DO NOT GET PROCESSED UNTIL THE LOOP ENDS.  I
//HAVE TRIED: t.sleep(), t.sleep(intervalBetweenMoves), //t.yield(), t.setPriority(Thread.PRIORITY_MIN), AND
//VARIOUS PERMUTATIONS.  IF ANY OF THESE METHODS ARE INDEED
//THE CORRECT ONES, THEN I AM NOT USING THEM CORRECTLY AND
//NEED TO KNOW THE RIGHT WAY TO USE THEM]
wait(intervalBetweenMoves);
}
Help appreciated!
Ben Drasin
0
Comment
Question by:drasin
  • 6
  • 3
  • 2
11 Comments
 
LVL 3

Expert Comment

by:gwalters
ID: 1232937
Here's what I usually do:


public void run()
{
  while (true) {
    switch (runAction) {
      case 0: //idle
        //you could do your movement here
        try {Thread.sleep(100);} catch (InterruptedException e){}
        break;

      case 1: //First action you want based on event
        //do the work
        runAction=0; //make idle again
        break;

      //more cases, as needed...
    }
  }
}

public boolean handleEvent(Event e)
{
  if (CONDITION1)
    mainAction=1;
  else if (CONDITION2)
    mainAction=2;
  else //...
  return super.handleEvent(e);
}


0
 

Author Comment

by:drasin
ID: 1232938
Tried it.  Does not work.  The main thread never even gets to set up the rest of the applet, because the selfish while loop never gives up control.  Sleep does not seem to be effective in this way; as I mentioned, I already tried this.  Is there anything else I need to be doing in order to get sleep to work? Or should I be using another method entirely?
0
 
LVL 2

Expert Comment

by:mgk
ID: 1232939
Why not use a named thread, similar to the rejected answer;

while (thread.currentThread==t) {
  <do stuff>
}

You want your run method to execute the code within it for that thread, and it's locking because you are putting it into an endless loop. Your wait(intervalBetweenMoves) is then just t.sleep(intervalBetweenMoves). I know you said this didn't work but I think it should if you just ditch the while(true) loop you're getting stuck in.

0
 
LVL 2

Expert Comment

by:mgk
ID: 1232940
I decided to add some code. It's primitive but it demonstrates what I'm getting at. Prints an ever incrementing number to standard output but will also report any events. I've marked it as an answer instead of a comment because if I think this should be what you need.



import java.applet.*;
import java.awt.*;

public class ThreadExample extends Applet implements Runnable{
      
      Thread            t;
      int                   i;
      
      public void start() {
            if (t==null) {
                  t=new Thread(this);
                  t.start();
            }
      }
      
      public void stop() {
            if (t!=null) {
                  t.stop();
                  t=null;
            }
      }
      
      public void run() {
            while (Thread.currentThread()==t) {
                  i++;
                  System.out.println(i);
                  try {
                        Thread.sleep(1000);
                  }
                  catch (InterruptedException e) {
                  }
            }
      }
      
      public boolean handleEvent(Event e){
            System.out.println(e);
            return super.handleEvent(e);
      }
}
0
 
LVL 2

Expert Comment

by:mgk
ID: 1232941
Huh?  The "selfish while loop" gives up the CPU every time through the loop for 100ms.  

Maybe the sleep time isn't long enough (although 100ms has always worked fine for me).  

Or maybe you're allowing mainAction to stay non-zero, in which case the while does indeed become a tight loop.


0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 3

Expert Comment

by:gwalters
ID: 1232942
Oops, of course I meant runAction
0
 
LVL 3

Expert Comment

by:gwalters
ID: 1232943
After re-reading your question, maybe the thing is that you don't want anything other than the sleep in "case 0".  Maybe your move() method is too costly to do every 100ms (and maybe it's not necessary until you get an event and set runAction to some non-zero value).

Anyway, the whole point is that you poll some variable in your thread that gets changed in the handleEvent thread.  How often you poll is important: too often and you load the CPU, too seldom and you get poor response to the event that set it.


0
 
LVL 3

Expert Comment

by:gwalters
ID: 1232944
Still no luck.  Let me fill you all in on what I have tried so far (I do appreciate your attempts, but regret that I cannot award points :-) ).
In my code for Gamescreen.handleEvent and GameManager.move() I
am System.out.println'ing the current time; this confirms that the events are not registering until after the loop exits (I have been alternating between the while loop and a long for loop).  In order to allow the applet to finish loading, I put an extra if statement in handleEvent to start the game on the first sucessful handling of the event.  Mabey I am just missing something which you assume I know.  I'raise the stakes in view of my increacing desperation. The following is raw, bare, naked code from my applet (well, almost):

From class gameScreen:
public boolean handleEvent(Event evt ) {
if (evt.id      == Event.MOUSE_DOWN) {
      System.out.println("Got Event: " + evt);
            if (gameStarted ==false){
                  startGame();
                  gameStarted = true;
      }      
              launchMissile(curBase, evt.x, evt.y);
            
      }
            return super.handleEvent(evt);
}      
public void launchMissile (int base, int x, int y ) {
      System.out.println("fired at " + System.currentTimeMillis());
      gameManager().addMissileStrike(new MissileStrike(0, 0 ,x, y, 5));
      return;
}
public void startGame( ) {
      System.out.println("Run, Will Robinson, run!");
      gameManager().thread().run();
}

And from class gameManager:
public void run() {
      System.out.println("GameManager running.");
      gameState = GAME_MOVING;
      loopAndMove();
}                              
public void  loopAndMove ( ) {      
      int a = 0;
      while(a < 500){                                             System.out.println(System.currentTimeMillis());
             System.out.println("loop# "+ a);
             a++;
             switch(gameState){//this was a nice touch,
                                 //gwalters, thank you!  Does
                                 //not solve my problem, though!
            case GAME_MOVING://Yes, I defined these ints.      
            System.out.println("About to move");
            move();                                                                                        gameState = GAME_IDLE;
                break;
                case GAME_IDLE:
            System.out.println("About to sleep");
            try{
               thread().sleep(delay);//tried various times.
            }// end try
            catch(InterruptedException e){}
              break;
            }//end switch            
      }//end while
}
When run, the consol reads:
Got Event: java.awt.Event[id=501,x=160,y=196,target=v1.GameScreen[canvas4,1,1,498x406]]
Run, Will Robinson, run!
886785708842
loop 0
886785709043
loop 1
886785709223
loop 2
886785709403
loop 3
886785709573
loop 4
...
...
loop 498
About to sleep
887041503538
loop 499
About to sleep
waiting
Got Event: java.awt.Event[id=501,x=202,y=257,target=v1.GameScreen[canvas0,1,1,498x406]]
Got Event: java.awt.Event[id=501,x=83,y=253,target=v1.GameScreen[canvas0,1,1,498x406]]
fired at 887041506012
Missile created at 887041506162
adding missile at 887041506242
there are now 1 missiles
this missile is aimed at 83 253
Got Event: java.awt.Event[id=501,x=249,y=133,target=v1.GameScreen[canvas0,1,1,498x406]]
fired at 887041507384
Missile created at 887041507534
adding missile at 887041507594
there are now 2 missiles
this missile is aimed at 249 133
Got Event: java.awt.Event[id=501,x=243,y=166,target=v1.GameScreen[canvas0,1,1,498x406]]
fired at 887041508716
Missile created at 887041508856
adding missile at 887041508926
there are now 3 missiles
this missile is aimed at 243 166

HELP!!
0
 

Author Comment

by:drasin
ID: 1232945
I couldn't make any sense out of:

gameManager().thread().run()


Assuming "gm" is the gameManager object, try
(new Thread(gm)).start()


In any case, call "start()" on a Thread object to get the "run()" method started.  Don't call "run()" directly.  The "start()" method returns immediately and starts a new thread.  Calling "run()" will block the current thread until it returns.

Anyway, as you can probably tell, ExpertsExchange mangles source code pretty bad.  If you want, you can send stuff to me at walters@ct.net


0
 
LVL 3

Expert Comment

by:gwalters
ID: 1232946
Here's the answer you asked me to post.
0
 
LVL 3

Accepted Solution

by:
gwalters earned 150 total points
ID: 1232947
Thanks for clearing up confusion between run() and start() methods of thread.  I guess every answer seems obvious once you know it.

0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now