stevi gefingerpokens jsam. jsam oufs! kristen has arrived. Tom gives jonathan another 60 seconds or so. User On Idle Doing Tom 1h 0s stalking the javawock bos 1h 4m magpie 43m 24s playing with my new boxing nun puppet josh 8m 13s caitlin 33m 15s starting the New Year with Civ II! catbear 2h 7m tapaboy 23h 2h KILL YOUR EVANGELIST troc 7h 25m whisper "rw" for a random [non-]word kristen 12m 44s back to normal, mostly. smarry 2h 32m the procrastination shuffle babs 1d 9m Not Quite Human Yet merde 34m 28s self-absorption. what else is new? stevi 6m 48s jsam 6m 1m LIVE FROM SUNNY 1998 corprew 7h 38m Michele 6h 16s http://www.boutell.com/squishy/index2.html AjD 6h 2s so this is 1997? doesn't seem like a big deal. Uptime: 10d End of List. You say, "well, that's about long enough, anyway." Stimulants Anonymous Welcome to the Java programmers' roasteria. A wide variety of stimulating beverages are consumed among the whirring virtual machines. Contents: Resources, Help, Java 101, Transcripts, Tom, stevi, jsam, kristen Visible Exits: n You say, "thanks for coming to the eighth meeting of the java class, folks." jsam smiles. You say, "before I start rolling, I'd like to ask if anyone has questions they would like to resolve before I cover new material." kristen has general confusion about threads and when you need them or not, but that's about it. % You have new mail in /var/spool/mail/boutell You say, "kristen: well, as a rule of thumb, if you want to do something that takes a lot of time, and you don't want to make the browser wait for you, it would be good to do it in your own thread." jsam has wondered a bit about observables. kristen says, "i started changing the sinewave application over to a fractal application with a button that starts a new fractal, and i started to lose focus on how to combine buttons and threads." kristen says, "okay." You say, "kristen: interesting. Yes, I can see the confusion there." You say, "kristen: one way to deal with that would be to just stop the old thread if any, and make a new one, when that button is clicked." kristen says, "i'd like to be able to halt the fractal in progress. right now it starts a new fractal. it works but it is really not very responsive. at the end of class i can pick your brain." kristen nods. hm. that sounds logical. You say, "okay. It happens that this week's material does more with threads, including some things relevant to what you are talking about." You say, "so I'm going to get started." You say, "Everyone, please open the following URL:" kristen says, "cool." You say, "http://boutell.com/~boutell/class/talk.html" You say, "log into it with your regular handle if you would and say hello, so I'll know you made it." You say, "you'll see what I mean when you get there." You say, "great, everyone made it to the server. That's a relief." stevi cheers Tom! jsam says, "whee!" You say, "now, there are a number of new things at work here." You say, "I'd like to start off by talking about the Internet for a moment. This may be old hat for you guys, but bear with me." You say, "the Internet is a collection of machines, each of which has a name, or at least a cryptic address." You say, "machines on the 'net can communicate with each other much like people with telephone lines." You say, "to talk to someone else, you need their phone number." You say, "also, they need to have a phone plugged in at that number, and they need to be listening for the ring." You say, "in Java, and in internet communications in general, we talk a lot about objects of the 'Socket' class." You say, "Sockets are a great deal like phones, in that you can use one to dial up someone else, or you can sit by one and listen for calls." You say, "in Java, we distinguish between these two cases. 'Regular' Socket objects are mostly used to call up a server somewhere." You say, "to call up a server, you need a hostname (or address), and you need a port number." You say, "the port number is like an extension in your company phone system. You may have quite a few of them." You say, "on the net, a lot of these 'extension' numbers are standardized. For instance, HTTP (the web protocol) listens on port 80." You say, "in Java, if we want to listen for incoming calls, we make a 'ServerSocket' object, and we pass the port number to the constructor." You say, "Java makes this very straightforward, and it's a lot easier than using sockets in most languages." % You have new mail in /var/spool/mail/boutell You say, "any questions so far, or should I forge ahead and look at the source to the client?" jsam is okay. stevi votes for forging. kristen is okay You say, "OK. Please click on the 'talk.Client' link and take a look at the source code to the Client class." You say, "notice the first line:" You say, "package talk;" You say, "this is how we announce that the classes in this file are part of a 'package.'" You say, "we are creating our own package, much like java.awt, for instance." You say, "all of the classes in this package can see each other's regular methods, not just public methods. The rest of the world can't." You say, "this is nice, because we can do what we want in our own code, without worrying about other programmers doing dumb things from outside." You say, "you'll find that, when you work with packages of your own, you want to add a directory of your own to your CLASSPATH setting, and keep your packages in subdirectories of that directory." kristen shivers about classpath settings. jsam wonders what CLASSPATH means with the various mac environments. You say, "in my case, I've added /home/boutell/public_html/class as one of the entries in my CLASSPATH, and so java tries looking in the 'talk' subdirectory of that when it sees a reference to that package." You say, "when web browsers access your applets, they will try subdirectories of the directory your web page is in, so you can just put packages in subdirectories of that. As I have here." You say, "ie, notice that talk.html is in ~boutell/class, and all the class files are in ~boutell/class/talk." % You have new mail in /var/spool/mail/boutell You say, "now, let's look at the code..." You say, "the init() method of Client is simple GridBagLayout stuff, which we've seen before, so I'm not going to go into detail there." You say, "essentially we're laying out the name entry field and the connect button and so forth." You say, "the next method is the action() method, which we've also seen before. Notice that, if we're not connected already, we call the connect() method there when the connect button is pressed, or the user hits return." You say, "now, the connect() method is where things get really entertaining." You say, "this method's purpose is to connect us to the server." You say, "let's look at the code:" You say, "outputStrings = new Vector();" You say, "here we're creating a Vector object. Vectors are handy for all sorts of things. They are a lot like arrays, except that they automatically grow as you add elements to them; they don't have a fixed size." You say, "this vector is going to be used to keep a queue of strings that need to be sent off to the server." You say, "ie, things the user has typed in." You say, "sure enough, the first thing we do after that is get the user's name out of the name field, and add that to the vector." You say, "next, we need to figure out the address of the server, and the port it is listening on." You say, "we do that using the getParameter() method, which is part of the Applet class." You say, "getParameter() lets us access the tags in the HTML page. tags, you'll recall, come between and ." You say, "if we have a tag like this:" You say, " 0) {" You say, "tring s = (String)" You say, "outputStrings.elementAt(0);" jsam says, "Tom, the API Documentation on Object doesn't mention the synchronized keyword, nor does it give an elegant explanation of wait(). Did you consult other sourcees or parts of the docs?" You say, "sam: well, I had past experience with 'synchronized', so I was able to puzzle it out." You say, "sam: it was one more piece." jsam says, "okay. I'll have to do some reading of the main LRM. thanks." You say, "let me repeat that..." You say, "while (outputStrings.size() > 0) {" You say, "'while there's stuff in the vector...'" You say, "String s= (String) outputStrings.elementAt(0);" You say, "'haul out the first element, which is a string...'" You say, "outputStream.writeUTF(s);" You say, "'and write it out to the socket.'" You say, "outputStrings.removeElementAt(0);" You say, "'now remove the element from the vector. Everyone else moves down one, so there's a new element zero if it's not empty yet.'" You say, "so this loop pulls each string out of the vector and flings it at the server, bazoom." You say, "now, let's take a peek at the inputLine method, which ends this particular class..." You say, "synchronized(outputStrings) {" You say, "'make sure no one else is messing with the vector...'" You say, "outputStrings.addElement(s);" You say, "'add the new input from the user...'" You say, "outputStrings.notify();" You say, "'and notify anyone who is waiting for the vector that it's ready for inspection.'" You say, "so, when the user keys in a fresh line of input, we add it to the output queue and call notify() on the queue to wake up the output thread, which is currently in a wait() call, hoping to hear from us." You say, "finally, we call chatFrame.outputLine(s); to send a copy of the line straight to the user. We do that to save the server the trouble of sending it all the way back to us (we typed it, we know what it says), and so the user gets prompt feedback." You say, "now, this code is actually a bit incorrect, I've noticed since writing it..." jsam notes that chapter 17 of the JLangSpec is the [D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D You say, "it works fine, but if the output thread is currently busy writing earlier output to the server, the user has to wait to get the lock on the queue; notice the synchronized() blocks." jsam says, "yuck. place to look for more information about sync/wait/notify/etc." You say, "this is more of a problem in the server code, which we'll look at next week, by which time I will most assuredly have fixed this wee problem." You say, "the fix, by the way, is to copy the queue to a separate Vector that no one but the output thread ever touches, and then end the synchronized block, before writing to the server, which is what takes time." You say, "I could leave this unfixed in the client, and no one would ever notice. In the server, though, it's a bigger issue. I can't make other connections wait while another user is written to; one lagged user could bog down everything." jsam nods. "Alternatively, you could build a thread-safe queue type." jsam says, "sorry, Queue class." You say, "now, if that makes your skull hurt, relax; please hit 'back' in your browser and click on 'talk.ChatFrame'..." You say, "and let me know when you're there." stevi says, "there." jsam is there. You say, "now, this class is a lot like various applets we've peeked at, in its general layout. The init() method sets up a GridBagLayout(), there's an action() method, and so on. Except that this class doesn't extend Applet; it extends Frame." You say, "pardon, there's no init() method, sorry to mislead." You say, "I put that clumsily." You say, "it's simple enough:" You say, "this class is a stand-alone frame, as you can see from using the client." You say, "to get a stand-alone 'unsigned applet window' frame like this, you extend the Frame class." jsam says, "where is it decided how large the frame (window) should be?" stevi says, "what does 'unsigned applet window' mean?" You say, "the constructor of this class first calls the constructor for the parent class (the 'superclass'), like so:" You say, "super("chat");" % You have new mail in /var/spool/mail/boutell You say, "the constructor for Frame just takes a window title." You say, "sam: in a moment." You say, "stevi: 'unsigned applet window' is Netscape-speak. It used to say 'untrusted applet window' which was their way of warning you not to believe that's REALLY a password prompt from your system, or whatever..." You say, "stevi: because there are obvious security fears about applets popping up misleading frames..." stevi ahhhs. i'd never have guessed that's what it meant. You say, "stevi: now they have a scam where you can pay a lot of money and get a cryptographic key in your applet, and then it's considered 'signed' and the broken key goes away. But you can still tell it apart from a regular window, which is good." jsam says, "interesting." You say, "so, the constructor's main task is to lay out the frame, using a GridBagLayout just as we tend to do for applet windows." You say, "'how big will the frame be' is a good question. One good answer is to call 'pack()' after doing all of your layout." % You have new mail in /var/spool/mail/boutell You say, "if you do that, java will look at the layout, determine how big your components 'want' to be, find the smallest rectangle that shrinky-dinks around that, and make the frame that big." You say, "I do this a lot, because the results are fairly attractive and you get the right amount of space." You say, "notice that I call show() right after pack(). Unlike most components, frames don't automatically display when they are created. You have to call show() when you're ready." You say, "I should also point out the outputText variable. This is of class TextArea, which is a new one. TextArea is a lot like TextField, except that it can be multiple rows of text." You say, "in this applet, we use a TextArea to display the server's output. That requires a bit of hacking, because TextArea doesn't support word wrap out of the box." % You have new mail in /var/spool/mail/boutell You say, "now, take a peek at the handleEvent method." You say, "handleEvent is a very important method in any component, because all Events come here first." You say, "usually, we want to stay out of the way, and let the default version of handleEvent() -- the one in our parent class -- do its job, which is often to call action() or mouseDown() or what have you." You say, "there are exceptions, though. In particular, if the user closes the frame using the system menu in the title bar, we will receive an Event.WINDOW_DESTROY event. And since there is no handy windowDestroy() method, we have to catch that here in handleEvent." You say, "people don't like frames that won't go away when asked, so it's important to do this." You say, "you can check the type of any event by looking at the id member, which could be MOUSE_DOWN or WINDOW_DESTROY, et cetera." You say, "so, in this frame, if we have received a WINDOW_DESTROY event, we call the disconnect() method in the Client object that created us." You say, "among other things, that method calls dispose() on the ChatFrame object. Calling dispose() is the correct way to get rid of 'real, important things' like windows on your screen that are attached to java objects." jsam says, "is dispose() a special method, or just a common name?" You say, "sam: a common name." You say, "the most important thing in this method, really, is what we do if we *don't* want to deal with the event." You say, "it is *very* important that we call the original version of handleEvent instead, and return the result of that." You say, "otherwise, lots of important things like action() and so forth will never be called." You say, "in Java, writing 'super.method()' is the right way to insist that we want the parent class version of the method, and not our own 'replacement.'" You say, "whee! We're out of time, folks." You say, "I can see that this example is going to keep us busy for a while." You say, "I'm going to stop and take any questions. Anything goes as far as difficulty is concerned." kristen has lots of questions but i think i need to sleep on them and absorb. jsam pauses, on phone. stevi's with kristen in the need to absorb phase. jsam says, "thank you for the class, Tom. that was a big learn." % You have new mail in /var/spool/mail/boutell stevi says, "yes, thank you, Tom." Tom nods. It's been a big learn for him today. A lot of wackiness with threads. jsam says, "My question regarding disposal is this: if you forget to close a socket but you lose all references to it, will it be automatically closed (eg, by garbage collection) or not?" You say, "thanks for participating." kristen says, "tom, so, for mixing buttons and threads, in my case. it should be just one thread that i want to stop and start again with one button. is that a wait/notify thing?" jsam also notes that on his mac netscape 3.01, the TextArea has scroll bars in two directions, and the font inside comes through as Chicago, not "Times Roman". kristen hsa 'pause/resume' and too much stuff in her brane. You say, "okay, let's see:" You say, "sam: if you lose *all* references to the socket? Yes, but there are no guarantees about when, you see. Garbage collection happens when it's convenient." You say, "sam: moral: call close() on sockets." You say, "kristen: well, it depends on what" You say, "kristen: that depends on what exactly the button is supposed to do?" jsam says, "tom: mmm, ok." kristen says, "it's supposed to start a fractal, and another one to pause it halfway if the person gets bored and wants to change colors." kristen says, "right now it does start the fractal, but my 'clear' button doesn't do anything until the fractal part is done completely (i expected that.)" stevi smooches all liberally and heads off. stevi has disconnected. stevi goes home. jsam MUST go and eat some lunch. Bye, folks. jsam disappears. % You have new mail in /var/spool/mail/boutell You say, "kristen: well, so you don't need to start from scratch?" You say, "or do you want it to start from scratch?" kristen says, "i'm not sure what you mean." kristen says, "oh: i'd like to either cancel the drawing wherever it is and start a new one, or maybe jus tpause." kristen says, "if i could figure out one or the other i'd be happy." kristen has no goals here besides figuring out how to make an applet that has interactivity. You say, "kristen: well, if you stash a reference to the thread in a member variable when you create it, then you can call stop() on that thread anytime." kristen says, "i hae an idea that one variable in the actual fractal part could stop it, but i don't know how to force the fractal method to pay attention to anything once it starts." You say, "kristen: which would zap the old one. Then you can just make a new one." kristen says, "hm. okay." kristen nods. kristen says, "zapping is good." kristen's applets and stuff all have the quality of something one would do on drugs. press the button, get a pretty thing. press it again and get more colors. whee. You say, "kristen: since your thread is a recursive beastie, not a simple looping beastie, pausing is more troublesome I guess." You say, "kristen: when do you sleep(), if ever?" kristen says, "yeah." kristen says, "it sleeps in the same place the sinewave did." kristen says, "it runs exactly like ht sinewave applet except the 'draw sinewave' was turned into a recursive fractal thing. and i tacked a button on outside the thread, in the begging." kristen says, "er, beginning." You say, "mmm... it's just that I gather your 'draw sinewave' method takes a long time and never sleeps on the way. Unless I've missed something. That should be fine, mind you, but Netscape doesn't have properly preemptive threads." kristen says, "hm. i don't have the code in fron to fme. but i remember it being MainThread.sleep(100) in the 'try' part." You say, "hmm, actually, I guess it does make sense." kristen says, "i can put it in the background and it will still draw, but it is just very laggy. when i bring the browser forward again it takes too long for it to 'refresh'" You say, "if it happens once every pass through your recursive function." kristen says, "from the offscreen image i guess." kristen nods. hm. kristen says, "well you've said a lot that makes sense. i think when i go dink with again i can play with the thread." You say, "coolness." Tom closes his log.