Programming 101 By Way of Java

Programming 101


By Way of Java


Instructor: T. Boutell


Transcript for 12/5/96


Stimulants Anonymous

Welcome to the Java programmers' roasteria. A wide variety of stimulating beverages are consumed among the whirring virtual machines.

You say, "Welcome to the sixth meeting of the Java class."
You say, "Would anyone like to show off homework URLs?"
URLs removed to spare the students' web servers. -T
Tom takes a moment to wallow in all these neat applets.
You say, "in the last class, we raced through the Graph applet at breakneck speed."
You say, "I said at the time that we'd be going over it in considerably more detail, and so we will."
You say, "everyone please turn to this URL: http://boutell.com/~boutell/class/Graph2.java"
You say, "this version of the applet is pretty much identical to the one we studied last week, in that it includes the offscreen image used as a 'scratchpad' before copying it to the screen. The 'Graph1.java' version does not have that feature, and it flickers terribly. I provided that to explain why the code is necessary."
You say, "last week, we reviewed the init method in somewhat reasonable detail, but I am going to discuss threads a bit more because they are an important concept."
You say, "Netscape, and most other web browsers, have a single 'flow of control' that deals with such things as keyboard and mouse events. Events are handled one by one in sequence."
You say, "when Netscape starts up your applet and calls your init() method, it does so as part of this main 'flow of control', or thread."
You say, "this is why the init() method has to do its business and return in a hurry. Otherwise, everything else waits for it, including menus of Netscape and so on."
You say, "fortunately, Java provides a handy way to create additional threads, which proceed *independently* of the main flow of control."
You say, "the Thread class is used to control threads. There is one object of class Thread associated with each flow of control in the program."
You say, "when you decide you want an additional thread, a question immediately comes up: what method does this new thread execute first?"
You say, "in Java, you solve this problem by implementing the 'Runnable' interface in one of your classes..."
You say, "and passing an object of that class to the constructor of the Thread class, like so: mainThread = new Thread(this); // if your applet implements Runnable"
You say, "when you say 'implements Runnable', you're just making a promise that you will implement a 'public void run()' method. All interfaces are 'promises' like this, saying that you'll provide one or more particular methods."
You say, "when you implement Runnable, any threads created with that Runnable will call the run() method of your class, as soon as you call start() on the thread object."
You say, "any questions so far?"
You say, "okay."
kristen is okay, sortof. Oog.
You say, "kristen: well, the gist is this: a thread is a separate flow of control where you can do anything you want, as long as you want, and not worry about keeping other stuff from happening. An interface is a promise to provide certain methods; if you've implemented one, you can pass off your object as supporting that interface."
kristen says, "i am just fuzzy on 'this'. is 'this' the object?"
You say, "aha. Yes. 'this' is a reference to the current object, the one the method belongs to."
kristen says, "can you explain the origin of 'this'? I understand that it is what you are passing to the Thread Constructor, but i am suddenly lost as to what path exactly it follows..."
You say, "it's usually implied but occasionally it's necessary to say it explicitly. If we had 'x' and 'y' members, we could write 'this.x' and 'this.y' but 'x' and 'y' are convenient shorthands."
You say, "kristen, think about it as english for a moment..."
You say, "when we write a method called 'move', that verb needs an object. The object, implicitly, is 'this'."
kristen no no that doesn't help. what does 'this' refer to in this program?
You say, "well, what class is this code a part of?"
kristen says, "Graph2."
You say, "yes. Which is our applet, correct?"
kristen says, "yes."
You say, "right. So in any method of the Graph2 class, the word 'this' refers to the object this method was called for -- the applet."
kristen ohs.
kristen says, "is the applet the object refered to?"
Tom nods.
You say, "you only need to take advantage of 'this' once in a while, but calling a method of another class and passing 'yourself' to it is one of those times."
You say, "are we ready to move on?"
kristen nods.
You say, "OK."
You say, "you might expect to be able to draw a line in your applet's window and assume it will stay there forever. Especially if you've programmed in environments like DOS and so forth that don't use windows."
You say, "it doesn't work that way in Java applets, because your window might be obscured by another window at any time, and then made visible again. It is your responsibility to draw the contents of the component when Netscape calls your 'update' method."
You say, "now, normally, the 'update' method just does this: it (1) erases your entire applet window, and (2) calls your 'paint' method."
You say, "this is OK if your display is only repainted once in a while. But this applet is different -- it is repainted constantly as the sine wave moves."
You say, "so we know update() is going to get called very often."
You say, "now, if you completely erase and redraw a component often, you get flicker, which is ugly."
You say, "so there are two problems at this point: we can't count on something we draw to just stay drawn, and the display flickers when we repaint it. Fortunately, we can fix both of these by creating an offscreen image to paint to, as I've discussed earlier."
You say, "the offscreen image is never 'obscured' or altered. The only price we pay for it is memory; but it's not so much memory that we need to be overly worried."
You say, "now that we've decided to use an offscreen image for our drawing, our update and paint methods become very simple. update just calls paint, *without* erasing the component first. And paint just copies the entire offscreen image to the real screen in one fell swoop."
You say, "any questions or confusion?"
kristen lemme read and grok a sec.
kristen nods.
You say, "okay. Now let's move on to the actual drawing."
You say, "take a look at the drawCurrentStep method."
You say, "note that this method is synchronized, and so is paint. That's because the web browser's main thread will call paint, but our own, independent thread calls drawCurrentStep -- and both of them want to play with our offscreen image. We synchronize them so they can't run at the same time, so an 'unfinished' image is never copied to the screen."
jsam says, "so no two synchronized methods of an object can run at once? if paint() called drawCurrentStep(), would deadlock occur?"
You say, "sam: no two synchronized methods of an object can run at once, yes. I believe there would be deadlock in the case you're asking about; I'm not entirely certain what the rule is. I wouldn't do it. Hee."
jsam smiles. "Cool."
You say, "the first thing we do in this method is get a Graphics object, which is a 'pen' used to draw on an image: Graphics g = offscreen.getGraphics();"
You say, "next, we call the clearImage method, which I'll look at in a bit."
You say, "OK. Now, next we set the drawing color. The Color class governs colors, and it has a number of convenient static final members representing popular colors -- red, white, black, et cetera. So we can say g.setColor(Color.red); if we want."
You say, "Color also has a constructor that takes red, green and blue byte values, so you can do any color you like."
jsam says, "where does createImage come from, btw?"
You say, "sam: createImage is a method of the Component class, as it happens. There's a reason why it's there and not a static method, but I'd rather not go into it just now. The gist is that you can call createImage within any component."
jsam nods. "Okay."
You say, "OK. Now, to draw the sine wave, we're going to need to calculate various points along the sine wave."
You say, "I could have calculated a Y value for every X value in the applet, by (let's say) scaling the range of X axis values to 0 through 360 degrees, and doing a computation for every point..."
You say, "I didn't do this, or more accurately I stopped doing this, because it was SLOW. That's a lot of math. It's also a lot of individual calls to draw little line segments, which are slow too."
You say, "instead, I skip along by four degrees at a time, and I connect a line segment back to the previous point..."
You say, "which is much faster, but still looks fairly smooth, because a lot of line segments approximate a curve pretty well."
You say, "I keep the y axis position from *last* time in the 'oldy' variable. The first time through the loop, I don't draw anything at all, since there's no 'old' point to connect to."
You say, "now, it occurs to me that I haven't covered the 'for' statement yet. Here's how it works:"
You say, "for (variable = startingValue; (boolean test); change-variable) { code }"
You say, "in essence, there are three clauses between the parentheses..."
You say, "the first one is typically a simple assignment, such as x = 0"
You say, "the second one is a condition. This is tested before every pass through the loop, including the first. When it ceases to be true, the code inside the { } block doesn't get run any more, and the for block ends."
You say, "the third statement is typically an increment (++ adds one) or decrement (-- subtracts one) operation. In this case, we want to skip by four, so we write += 4. Operators like += are handy shorthands for 'x = x + 4'."
You say, "I apologize if this is old hat for the studio audience."
You say, "any questions about this method, since it does the actual drawing?"
kristen nope.
jsam is fine.
You say, "okay. Let's look at the 'run' method briefly, since this is the 'heart' of the applet, where our thread lives."
You say, "this method is an endless loop; it keeps going until someone calls stop() on the thread. We never do, but Netscape might if it feels like it."
You say, "the moveOneStep() method advances the graph by one degree. It also calls 'sleep' on our thread object, because I lied a little bit: your threads do need to spend a little bit of time sleeping to make sure other threads can run. I won't defend this, it's a shame and they could have done better, but if you sleep at least 20 milliseconds just about all browsers will behave properly."
jsam says, "java threads are cooperative?"
You say, "jsam: yes, java threads are cooperative in a lot of implementations, although they are 'supposed' to be preemptive, safe, fire-and-forget things of wonder. Oh well. In practice, only Microsoft Internet Explorer seems to have threads that don't need sleep() calls."
You say, "and there are simpler ways to write Microsoft-only applications, eh?"
jsam nods.
You say, "there's a try { } block around the call to sleep because it's possible for an 'InterruptedException' to occur if another thread calls resume() on this thread. We don't care, so we catch all exceptions and do nothing with them."
You say, "okay. The final method, for the record, is clearImage, which sets the color to black and fills the image with a black rectangle. We pass a Graphics object to it, which is convenient because it might refer to the applet window itself or to our offscreen image."
You say, "now, any further questions on this applet? I have another to play with if we're raring to go."
kristen wants to know how come my applet caused an exception for stevi.
You say, "well, that's a good question. It didn't for me. Applets with threads can be a bit problematic at times, and in general java implementations still have bugs. Did the browser crash, kristen?"
kristen says, "i don't know. it has worked alright for me."
You say, "well, if the browser crashed, it's a bug in the browser, since no java applet should ever be able to do that, buggy or otherwise..."
You say, "but if you can reproduce it somewhere convenient, you might play with commenting things out and so forth to try to track it down."
jsam says, "do you always have to say "Math.sin()", or if you "import Math;" can you just use "sin()"?"
You say, "jsam: you still have to say Math.sin(). At least you're spared the full package name of the class."
You say, "shall I trot out the new applet?"
kristen says, "sure."
You say, "all righty then."
You say, "please open up this URL:"
You say, "http://boutell.com/~boutell/class/BeamApplet.html"
jsam j-wubs.
You say, "let me know when you stop giggling for a moment."
jsam says, "super-cool, tom."
kristen says, "neeeeet."
You say, "the game doesn't currently celebrate when someone wins. Also, there are occasional problems with the restart option. I will clean this one up before the next class."
You say, "for now, I'll give a quick overview of the code."
You say, "like the Graph applet, this one takes advantage of an offscreen image."
You say, "also similar to the Graph applet, threads are used."
You say, "this time, though, there's one thread for each of the 'Beam' objects."
You say, "I made the BeamApplet object responsible for the 'playfield'; it contains a grid with a boolean value for each 'space' a Beam might try to enter. Those flags are set true when a Beam passes into them."
You say, "notice this member of the BeamApplet class:"
You say, "boolean grid[][]"
You say, "this is an array; actually, it's an array of arrays. Which sounds a bit much, but it's just a two-dimensional grid."
You say, "the restart() method is responsible for setting up the game and creating new Beam objects to run free in it."
You say, "the array of booleans is created like this:"
You say, "grid = new boolean[gridWidth][gridHeight];"
You say, "now, I realize that grid is an array of booleans, and that booleans, like integers, don't need 'new' called to create them."
You say, "what we're creating with 'new' is the *array of* booleans -- which *is* an object."
You say, "well, the next possibly unfamiliar step is this:"
You say, "beams = new Beam[3];"
You say, "here we are creating another array, this time a single-dimensional array of Beam objects."
You say, "as I mentioned, creating the objects themselves is a separate step. Right now, beams[0] through beams[2] are all 'null' references."
You say, "so now we create actual objects. For instance:"
You say, "beams[1] = new Beam(this, Color.cyan, Color.blue);"
You say, "this lets us keep a reference to that beam for later use, the next time we restart, so we can stop it."
You say, "notice that when we create the player's beam, we actually create an object of a different class, 'PlayerBeam.' It's OK to store this in the array because it is a subclass of Beam."
You say, "most of the fun is in the Beam class itself, and in the PlayerBeam subclass. Notice that the Beam class has a 'think' method which decides where to go next..."
You say, "in the PlayerBeam class, this method is replaced with a method that does nothing at all -- because the thinking is up to the human player."
You say, "instead, for that class, I pass in keyboard events from the applet itself."
You say, "later I can rig that up so multiple players are permitted, or even in theory for network play."
You say, "kristen, you might find the randomBetween() method in this class useful."
You say, "feel free to copy it into your stuff as needed. It returns an integer between x and y, inclusive, which is a pretty common request."
kristen nods.
You say, "now, I'm not going to try to cover methods of this applet in baroque detail tonight in the remaining five or so minutes, so I'm going to answer questions and cover anything you find of interest in the time we have left."
jsam says, "do you know why restarting sometimes gets stuck?"
You say, "sam: not yet."
You say, "sam: I got an interesting error message when running it on boutell.com. I'll have to test it a lot in the appletviewer, which seems the least buggy and the best at politely reporting mistakes on my part."
jsam says, "it's safe to stop() a thread twice?"
You say, "sam: I don't know for sure, but I don't think I ever do that. I set myThread to null immediately after stopping it."
jsam says, "oh."
Tom puts the chalk down. Thanks for a good class.

Next | Up to the Index

Follow us on Twitter | Contact Us

Copyright 1994-2012 Boutell.Com, Inc. All Rights Reserved.