aspose file tools*
The moose likes Threads and Synchronization and the fly likes Using Threads Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Using Threads" Watch "Using Threads" New topic
Author

Using Threads

Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Hi all,
I am trying to write a simple application that will display a moving ball within a frame. All that happens when I run the program is that a frame is displayed but there is nothing within it, no ball, nothing, just an empty frame. I dont know what Im doing wrong. My code follows.
import java.awt.*;
import java.awt.event.*;
public class balls extends Frame implements Runnable
{
Point ballPos=new Point(10,10);//A coordinate that holds the x & y position of the ball
Point ballChg=new Point(2,2);//A coordinate that holds the values by which the ball position change s
public balls()
{
super("Bouncing balls");
}
public static void main(String arg[])
{
balls ballFrame=new balls();
Thread b1=new Thread(ballFrame);
b1.start();
ballFrame.setSize(700,600);
ballFrame.show();
ballFrame.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent we){System.exit(0);}});
}
public void run()
{
while (true)
{
repaint();
try{Thread.sleep(500);}
catch(InterruptedException ie){}
if (ballPos.x<=10 || ballPos.x>=getSize().width) ballChg.x=-ballChg.x;
if (ballPos.y<=10 || ballPos.y>=getSize().height) ballChg.y=-ballChg.y;
ballPos.x+=ballChg.x;
ballPos.y+=ballChg.y;
}
}
public void paint(Graphics g)
{
g.setColor(Color.blue);
g.fillOval(ballPos.x,ballPos.y,10,10);
}
}
What is going wrong? Why dont I see anything in the frame?


May the force of the Java be in all of us !!!
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hey Shash,
The problem is that your conditionals are not allowing the ball to move. Try this:

Note that all you really had to do here was change the <= and >= to < and >.
Hope this helps,
Michael Morris


Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Michael,
Thanks a million. It did work, but Im still perplexed as to why the <= and the >= would make the code not work properly.
<= means less than or equal to while < means less than, so shouldnt the conditional of x<=y hold true at a point where x<y? By saying x<=y, am I not just saying that I want the point x=y also to be included? Why then does the condition <= and >= not work?
I did some more tweaking o the conditional statements and the code works fine if I have all four conditionals as < and >. It also works if I have the >= in the second part of the compound conditionals , but it does not work if ai have the < and > in the first part of the conditionals, regardless of whether the second part has > or >=. This is more confuusing.
In other words
if (x<y || x>=y) ... works
if (x<y || x>y) ... works
but
if (x<=y || x>y) ...
if (x<=y || x>=y) ... do not work
Weird huh? Why is this happening?
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
The best way to see this is to uncomment the System.out line in the paint method and watch the values change. That's how I caught your problem. Your inc values were resetting on every pass, so the ball "was stuck in the mud."
Hope this helps,
Michael Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
michael,
Got it so far.
Now what I am trying to do is to rerite the same program, but define the ball in a separate class, either as a nested class or a separate class altogether. I couldnt get either of these attempts to work. My code follows
attempt at using ball as an inner class
*********
import java.awt.*;
import java.awt.event.*;
public class bounce extends Frame implements Runnable
{
class ball
{
int x,y,dx,dy;
ball()
{
x=10; y=30;
dx=10; dy=10;
}
}
public bounce()
{
super("Bouncing balls");
}
public static void main(String arg[])
{
bounce ballFrame=new bounce();
Thread b1=new Thread(ballFrame);
b1.start();
ball b=new ball();
ballFrame.setSize(700,600);
ballFrame.show();
ballFrame.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent we){System.exit(0);}});
}
public void run()
{
while (true)
{
repaint();
try{Thread.sleep(24);}
catch(InterruptedException ie){}
if (b.x<10 || b.x>=getSize().width) b.dx=-b.dx;
if (b.y<10 || b.y>=getSize().height) b.dy=-b.dy;
b.x+=b.dx;
b.y+=b.dy;
}
}
public void paint(Graphics g)
{
g.setColor(Color.blue);
g.fillOval(b.x,b.y,10,10);
}
}
**************
When I tried to compile this, I got 15 errors messages, each of which said
Cannot resolve symbol
Symbol b
b.y+=b.dy;
^
Dont understand why. I get the same errors if I move the ball class outside the bounce class
Actually I get 15 errors saying they cannot resolve symbol b
import java.awt.*;
import java.awt.event.*;
class ball
{
int x,y,dx,dy;
ball()
{
x=10; y=30;
dx=10; dy=10;
}
}
public class bounce extends Frame implements Runnable
{
public bounce()
{
super("Bouncing balls");
}
public static void main(String arg[])
{
bounce ballFrame=new bounce();
Thread b1=new Thread(ballFrame);
b1.start();
ball b=new ball();
ballFrame.setSize(700,600);
ballFrame.show();
ballFrame.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent we){System.exit(0);}});
}
public void run()
{
while (true)
{
repaint();
try{Thread.sleep(24);}
catch(InterruptedException ie){}
if (b.x<10 || b.x>=getSize().width) b.dx=-b.dx;
if (b.y<10 || b.y>=getSize().height) b.dy=-b.dy;
b.x+=b.dx;
b.y+=b.dy;
}
}
public void paint(Graphics g)
{
g.setColor(Color.blue);
g.fillOval(b.x,b.y,10,10);
}
}

What am I doing wrong here?

[ February 04, 2003: Message edited by: Shashank Gokhale ]
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
The main problem here is that the Ball object needs to be part of Bounce's state. By constructing it in main(), Bounce has no reference to it.
Try this:

Hope this clears it up,
Michael Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Michael,
Good show.
Thanks. I had the same thing earlier as what you have, with the class Ball being a nested class and the Ball constructor getting called in the Bounce constructor. The only difference I had was that instead of having the line
private Ball b;
I had the line
Ball b;
I dont see why it makes a difference. But I could have had some other differences too, but I dont think I did.
Anyway, now how would you have the code so that the ball.class is outside the bounce class.
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
Just move it outside, either in the same file or a different file. So long as it is in the classpath and properly imported, both compiler and interpreter will have no problem finding it.
About the private declaration, a good rule to follow is to always declare an instance variable private unless there is a compelling reason to open up the scope such as anticipating a subclass needing access to it, in which case you would change the modifier to protected. Even opening it up in that scenario is questionable since a better practice is to define getter and setter methods for any instance variables that might need to be accessed.
Hope this helps,
Micheal Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Michael,
You are 100% right about declaring membr variabless private. I just didnt because I wanted to get a better understanding of Threads.
Im not too clear on what
Thread b=new Thread(this) is saying
and something like
Thread b=new Thread(Runnable object) is saying
So far Ive been going with seeing what works and if something works, its a learning experience. But I havent a clue on what the above two statements would signify. Can you clarify?
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
The Thread class has many constructors but by far the most important and most used is Thread(Runnable runner). Once constructed, calling the thread's start() method causes the thread to be scheduled to run. Once the scheduler gives our newborn thread the ball, it then calls the run() method of the Runnable object that we passed in the constructor. When the run() method terminates either naturally or by throwing an exception, then our thread dies and can never run again. We can construct a new thread with the same Runnable and start it if we want though. That's why you usually see either an infinite loop (while(true)) or a loop that terminates when our thread has finshed it's work defined in the Runnable's run() method.
As for new Thread(this), that always indicates that this implements Runnable and of course has a run() method. You'll generally see constucts like that when you have a single class that needs to do a lot of computing and can generate multiple threads to perform it's work in parallel.
The Thread constructors that don't take a Runnable in order to actually run will have to be subclassed and the subclass will have to override the Thread's run() method. Most OO experts frown on extending the Thread class though since it is then actually performing two duties instead of its primary duty. That's called a schizophrenic class. One exception to this would be if you were implementing a Thread pool to conserve system resources since there are a limited number of threads available to any application.
Hope this clears it up,
Michael Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Michael,
Cool, its clear so far, until I run into another thing that I dont understand.
What I am planning to do now is to try and code my program so that insteead of just one ball in the frame, I have multiple balls going about the frame, each started when I click a button. And I also want to be able to control the start location of the balls when they are instantiated, as well as the speed. So I guess I may have some future question about KeyListener and ActionListener. I may not use ActionListener since I dont think Ill be using buttons.
So until next time, maybe in a diffferent forum. Thanks so far. I probably will have some questions on how to use multiple threads. But till then all is well
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Hi again Michael,
I was trying to code the program for multiple balls, and initially I thought of using a vector to hold the multiple instances but i dont know how to use vectors yet. Can you show me how to declare a vector? Anyway, I went to arrays, but got stuck, becuase I would need to call the Bounce2 (class Bounce is Bounce2 in the file I copied Bounce to)constructor more than once, but Bounce2 is a frame, so if I call it more than once, am I not creating several frames as well?
And can I put the call to a constructor in my anonymous class of KeyAdapter?
The xode I hhave thus far is
import java.awt.*;
import java.awt.event.*;
class Ball
{
int x,y,dx,dy;
Ball()
{
x=(int)(Math.Random()*getSize().width);
y=(int)(Math.Random()*getSize().height);
dx=(int)(Math.Random()*10);
dy=(int)(Math.Random()*10);
}
}
public class Bounce2 extends Frame implements KeyListener, Runnable
{
/* Ball object needs to be part of the state of Bounce for painting. */
//added an array of 10 balls<<<<<<<<<<<<<<<<<<
private Ball b[]=new Ball[10];
//ballcount is a count of the number so far<<<<<
static int ballCount=0;
public Bounce2()
{
super("Bouncing balls");
/*This is where we need to construct our Ball object so we will have a reference to it for painting.*/
//add a new ball to the array
if (ballCount<b.length) b[ballCount++] = new Ball();
}
public static void main(String arg[])
{
Bounce2 ballFrame=new Bounce2();
Thread b1=new Thread(ballFrame);
b1.start();
/* We can't call this from a static context (main() is static) unless the class is declared static. Besides, our ballFrame needs a reference to the Ball object to do the painting. So it does no good to construct it here.*/
// Ball b=new Ball();
ballFrame.setSize(700,600);
ballFrame.show();
ballFrame.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent we) {System.exit(0);}});
ballFrame.addKeyListener(new KeyAdapter(){public void keyPressed(KeyEvent ke) {/*add what here*/};}});
}
public void run()
{
while (true)
{
repaint();
try{Thread.sleep(24);}
catch(InterruptedException ie){}
if (b.x<10 || b.x>=getSize().width) b.dx=-b.dx;
if (b.y<10 || b.y>=getSize().height) b.dy=-b.dy;
b.x+=b.dx;
b.y+=b.dy;
}
}
public void paint(Graphics g)
{
g.setColor(Color.blue);
g.fillOval(b.x,b.y,10,10);
}
}
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Does that code compile?
What you need to do for one thing is in your run method you need to manipulate each of the 10 balls one at a time. You need a for loop something like

exactly what do you want to happen when you hit the key?
This paint method should be moved to the ball class.

the frame class paint method should call the balls paint methods 1 at a time. then call super.paint(g);
[ February 04, 2003: Message edited by: CL Gilbert ]
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
When I hit a key, I want the vent to spawn a new ball, add that ball instance to the array. Then of course in the run method, I want to paint each ball at the coordinates of that ball. What I also want to do is to have each ball run in its own thread.
What should be done?
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
To have multiple balls, you need ti Ball class to implement Runnable instead of Bounce. I've put together a framework with some improvements for you. I realize that you will probably have some questions about some of this so feel free to ask.
Ball.java

Sleeper.java

BallTimer.java

Bounce2.java

This just starts three balls to moving. I'll leave it up to you to add key events or maybe some buttons to add and delete balls dynamically.
Hope this helps,
Michael Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Whoa Michael,
You have a really good knowledge of Java. Kudos to you. The last message you posted has a lot of information in it, I will have questions definitely. Like for example,
Why did you use a Set to store the balls, why not a Vector?
I haent used the Iterator and stuff yet; Im guessing all it does it iterate, but then why couldnt you use a for loop to do that?
What is a hashtable?
Im not sure what wait, notify, notifyAll do except that wait causes the current Thread to wait in a ready state so that when another thread yields the CPU to it, it starts running again. I dont know how notify and notifyAll differ in what they do, because if notifyAll tells all waiting threads that it has yielded the CPU, then does notify send the same message to a particular thread?
Why do you need to code an interface when the interface only has a method declaration and not an implementation? Wouldnt class Ball that implements the method wakeUp() have done so even without implementing the Sleeper interface?
Thats the questions so far, Im sure Ill have lots more later.
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,

Why did you use a Set to store the balls, why not a Vector?

The Vector class is part of the older Collections API, so I chose one of the newer Collections namely Set since I don't need to map the objects that I'm storing. A Set does not allow duplicate objects so it was a good choice here.


I haent used the Iterator and stuff yet; Im guessing all it does it iterate, but then why couldnt you use a for loop to do that?

Well, since the implementation that we chose for our Set was a HashSet, then the objects are stored in the Set in no particular order (it actually uses the value returned by Object.hashCode() to store the objects). We could convert it to an array every time but that would be dreadfully inefficient and wasteful. So we grab its iterator and one by one process the objects in the Set.

What is a hashtable?

A Hashtable is also one of the older Collections. You should avoid it and use a HashMap instead. Both implement the Map interface which in essence means that they map keys to values. The key can be any object with a unique hashCode() and the value can be any object regardless of hashCode() it can even be null for a HashMap, but not for a Hashtable. The Map interface is very handy for cataloging things for example, a cell ID for the key and a Cell object for the value.

Im not sure what wait, notify, notifyAll do except that wait causes the current Thread to wait in a ready state so that when another thread yields the CPU to it, it starts running again. I dont know how notify and notifyAll differ in what they do, because if notifyAll tells all waiting threads that it has yielded the CPU, then does notify send the same message to a particular thread?

All of the Object.wait() methods cause the currently executing thread to stop execution (which allows the thread scheduler to randomly select some other thread to run) and go into the wait pool of whatever object wait() is called on. That object could have any number of threads at any given time waiting in the pool. The notify() method causes the scheduler to arbitrarily choose one thread to wake from the pool. The notifyAll() causes the scheduler to wake all threads waiting in the pool. In either case, the thread(s) will have to wait its(their) turn restart execution. When a thread does restart, it begins right after the wait() call. Notice that wait(), notify() and notifyAll() must be called from a synchronized block. That block can be a whole method are an arbitrary block inside the method and can synchronize on whatever object you like. I always prefer to synchronize the whole method since it is less prone to deadlocks. A deadlock occurs when all running threads have encountered a wait() and none are running. That's why it's important to make sure you balance your wait() and notify()/notifyAll() calls.

Why do you need to code an interface when the interface only has a method declaration and not an implementation? Wouldnt class Ball that implements the method wakeUp() have done so even without implementing the Sleeper interface?

Becuase Interfaces is da man! But seriously, note that both our Ball class and our Bounce2 class implement the Sleeper interface. Further note that the BallTimer$WakeUpTheBalls class has to call the wakeUp() method on all the Balls as well as the Bounce2 Frame. Since the iterator.next() returns an Object and not a Ball or Bounce2, in order to call the wakeUp() method, we need to typecast the returned Object to something that has a wakeUp() method. Now we could have done something like this instead:

but since we had them both implement the Sleeper interface, all we have to do is instead check for and cast to the interface which is guaranteed to have a wakeUp() method. As you can see, this is much easier than constructing a conditional for every class that may have a wakeUp() method.
Of all the features of Java, interfaces are what really sets it apart from the rest. As you learn more about OO programming and Java you'll come to depend on interfaces more and more.
Hope this explains it,
Michael Morris
Shashank Gokhale
Ranch Hand

Joined: Jan 07, 2003
Posts: 90
Michael,
Hi. I am going to take some time to wade through the program you sent me. I need to follow it first before I can ask any intelligent questions. In the meantime, I tried to modify my program, along with parts of the one you provided, to try and make 10 balls move around. But they just stay still. What can I do in the following program to make them move. Sms like the run method is never getting called, although I dont have any real basis for saying this. Its just that if the balls dont move, I dont see threads in action. So what is going on?
import java.awt.*;
import java.awt.event.*;
class Ball implements Runnable
{
int x,y,dx,dy;
Color color;
Ball()
{
color=new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
x=(int)(Math.random()*400);
y=(int)(Math.random()*300);
dx=10;
dy=20;
}
public synchronized void run()
{
while (true)
{
try {wait();}
catch(InterruptedException ignore) {}
if (x < 10 || x >= 400) {dx = -dx;}
if (y < 10 || y >= 300) {dy = -dy;}
x += dx;
y += dy;
}
}
}
public class Bounce extends Frame
{
static int ballCount=0;
private Ball b[]=new Ball[10];
public Bounce()
{
super("Bouncing balls");
for (int i=0;i<b.length;i++) {b[ballCount] = new Ball(); new Thread(b[ballCount]).start(); ballCount++;}
addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent we) {System.exit(0);}});
setSize(700,600);
show();
}
public static void main(String arg[])
{
Bounce ballFrame=new Bounce();
}
public void paint(Graphics g)
{
for (int i=0;i<b.length;i++)
{
g.setColor(b[i].color);
g.fillOval(b[i].x,b[i].y,10,10);
}
}
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Shash,
Well you had a few little problems that kept the balls from moving. I made the changes here:

The main problems were:
  • Once a ball thread started running it immediately called wait() and went to sleep with no hope of ever waking since neither notify() nor notifyAll() were ever called
  • repaint() was never called to tell the Frame to repaint itself


  • So we create a private method moveTheBalls() that calls the newly created move() method on each ball after sleeping for 24 millisecs (it would be better to use a timer for this but until you're comfortable with that sleep() will suffice) then calls repaint(). We call moveTheBalls() at the end of every paint.
    Hope this helps,
    Michael Morris
    merlin bar
    Ranch Hand

    Joined: Feb 16, 2003
    Posts: 54
    Shashank, if you use around your code, it's a lot easier for us to read it. Thanks


    Regards,<br /> merlin_bar
    Shashank Gokhale
    Ranch Hand

    Joined: Jan 07, 2003
    Posts: 90
    Merlin,
    I dont understand what youre saying. What does that mean, use AND around my code?
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    He meant use tags like this:
    [ code ]
    sample code
    [ /code ]
    except without the spaces inside the []. If I'd written the tags properly, they would disappear, the font would change, and (most importantly) any indentation of the enclosed code would appear correctly. So for example you can get

    rather than
    for (int i = 0; i < 10; i++) {
    if (i % 2 == 0)
    System.out.println("even");
    else
    System.out.println("odd");
    }
    [ February 28, 2003: Message edited by: Jim Yingst ]

    "I'm not back." - Bill Harding, Twister
    Shashank Gokhale
    Ranch Hand

    Joined: Jan 07, 2003
    Posts: 90
    I agree with the use of the code tags. I have started using them now, but earlier I did not know that they were there
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Using Threads
     
    Similar Threads
    Need help breaking up this code
    why can't I access my variable?
    Using threads
    Beginner game
    Bouncing balls