Solved

Thread problem is ruining my life

Posted on 1998-02-08
11
199 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
java jdbc batch example 8 41
throw exception 21 58
maven disable workspace resolution 1 22
Running JavaFX on the Raspberry Pi 27 45
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

829 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