Solved

Thread problem is ruining my life

Posted on 1998-02-08
11
200 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Configure a Bean in an XML file 4 48
runtime exception 2 50
Fast way to search item into Java Array (Rhino compatible) 2 37
web project error add remove 1 49
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

735 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