📄 http:^^www.cs.wisc.edu^~cs537-1^java-tutorial.html
字号:
<em>No two threads may be executing <samp><font color="0f0fff">synchronized</font></samp> methods of thesame object at the same time.</em></center><p>The Java system enforces this rule by associating a <em>monitor lock</em>with each object.When a thread calls a <samp><font color="0f0fff">synchronized</font></samp> method of an object,it tries to grab the object's monitor lock.If another thread is holding the lock, it waits until that threadreleases it.A thread releases the monitor lock when it leaves the <samp><font color="0f0fff">synchronized</font></samp>method.If one <samp><font color="0f0fff">synchronized</font></samp> method of a calls contains a call to another,a thread may have the same lock ``multiple times.'' Java keeps trackof that correctly. For example,<pre><font color="0f0fff"> class C { public synchronized void f() { // ... g(); // ... } public synchronized void g() { /* ... */ } }</font></pre>If a thread calls <samp><font color="0f0fff">C.g()</font></samp> ``from the outside'', it grabs thelock before executing the body of <samp><font color="0f0fff">g()</font></samp> and releases it when done.If it calls <samp><font color="0f0fff">C.f()</font></samp>, it grabs the lock on entry to <samp><font color="0f0fff">f()</font></samp>,calls <samp><font color="0f0fff">g()</font></samp> without waiting, and only releases the lockon returning from <samp><font color="0f0fff">f()</font></samp>.<p>Sometimes a thread needs to wait for another thread to do somethingbefore it can continue.The methods <samp><font color="0f0fff">wait()</font></samp> and <samp><font color="0f0fff">notify()</font></samp>, which are defined in class<samp><font color="0f0fff">Object</font></samp> and thus inherited by all classes, are made for this purpose.They can only be called from within <samp><font color="0f0fff">synchronized</font></samp> methods.A call to <samp><font color="0f0fff">wait()</font></samp> releases the monitor lock and puts the calling threadto sleep (i.e., it stops running).A subsequent call to <samp><font color="0f0fff">notify</font></samp> on the same object wakes up the threadthat has been sleeping the longest time and lets it start running again.If no thread is sleeping in this object, <samp><font color="0f0fff">notify()</font></samp> does nothing.The awakened thread has to wait for the monitor lock before it starts, but ithas precedence over any other thread trying to enter a <samp><font color="0f0fff">synchronized</font></samp>method ``from the outside''.The method <samp><font color="0f0fff">notifyAll</font></samp> is similar, but wakes up <em>all</em> threadssleeping in the object.<pre><font color="0f0fff"> class Buffer { private Queue q; public synchronized void put(Object o) { q.enqueue(o); notify(); } public synchronized Object get() { while (q.isEmpty()) wait(); return q.dequeue(); } }</font></pre>This class solves the so-call ``producer-consumer'' problem (it assumesthe <samp><font color="0f0fff">Queue</font></samp> class has been defined elsewhere).``Producer'' threads somehow create objects and put them into the buffer bycalling <samp><font color="0f0fff">Buffer.put()</font></samp>, while ``consumer'' threads remove objects fromthe buffer (using <samp><font color="0f0fff">Buffer.get()</font></samp>) and do something with them.The problem is that a consumer thread may call <samp><font color="0f0fff">Buffer.get()</font></samp> onlyto discover that the queue is empty.By calling <samp><font color="0f0fff">wait()</font></samp> it releases the monitor lock so that producer threadscan call <samp><font color="0f0fff">put()</font></samp> to add more objects, but it keeps its place in lineso it will get an object before other consumer threads that arrive later.Each time a producer adds an object, it calls <samp><font color="0f0fff">notify()</font></samp> just incase there is some consumer waiting for the object.<p>This example is not correct as it stands (and the Java compiler will rejectit).The <samp><font color="0f0fff">wait()</font></samp> method can throw an <samp><font color="0f0fff">InterruptedException</font></samp>exception, so the <samp><font color="0f0fff">get()</font></samp> method must either catch it or declarethat it <samp><font color="0f0fff">throws InterruptedException</font></samp> as well.The simplest solution is just to catch the exception and ignore it:<pre><font color="0f0fff"> class Buffer { private Queue q; public synchronized void put(Object o) { q.enqueue(o); notify(); } public synchronized Object get() { while (q.isEmpty()) { try { wait(); } catch (InterruptedException e) {} } return q.dequeue(); } }</font></pre>There is also a version of <samp><font color="0f0fff">Object.wait()</font></samp> that takes an integerparameter.The call<samp><font color="0f0fff">wait(n)</font></samp> will return after <samp><font color="0f0fff">n</font></samp> milliseconds if nobody wakesup the thread with <samp><font color="0f0fff">notify</font></samp> or <samp><font color="0f0fff">notifyAll</font></samp> sooner.<p>You may wonder why <samp><font color="0f0fff">Object.get()</font></samp> uses <samp><font color="0f0fff">while (q.isEmpty())</font></samp>rather than <samp><font color="0f0fff">if (q.isEmpty())</font></samp>.In this particular case, either would work.However, in more complicated situations, a sleeping thread might beawakened for the ``wrong'' reason. Thus it is always a good ideawhen you wake up to recheck the condition that made to decide to goto sleep before you continue.<a name="io"><h2> Input and Output </h2></a><p>Input/Output, as described in Chapter 11 of the Java book, isnot as complicated as it looks.You can get pretty far just writing to <samp><font color="0f0fff">System.out</font></samp> (which is oftype <samp><font color="0f0fff">PrintStream</font></samp>) with methods <samp><font color="0f0fff">println</font></samp> and <samp><font color="0f0fff">print</font></samp>.For input, you probably want to wrap the standard input <samp><font color="0f0fff">System.in</font></samp>in a <samp><font color="0f0fff">DataInputStream</font></samp>, which provides the handy method<samp><font color="0f0fff">readLine()</font></samp><pre><font color="0f0fff"> DataInputStream in = new DataInputStream(System.in); for (;;) { String line = in.readLine(); if (line == null) break; // do something with the next line }</font></pre><samp><font color="0f0fff">DataInputStream</font></samp> has lots of other methods, but they probablydon't do what you expect.For example <samp><font color="0f0fff">DataInputStream.readInt()</font></samp> reads four bytes ofraw data and concatenates them to form a binary integer.If the next four bytes of input are the ASCII characters <samp>"1234"</samp>,<samp><font color="0f0fff">readInt()</font></samp> will return 825373492.<p>If you want to read from a file, rather than from the keyboard (standardinput), you can use <samp><font color="0f0fff">FileInputStream</font></samp>, probably wrapped ina <samp><font color="0f0fff">DataInputStream</font></samp>.<pre><font color="0f0fff"> FileInputStream rawInput = new FileInputStream("somefile"); DataInputStream in = new DataInputStream(rawInput); for (;;) { String line = in.readLine(); if (line == null) break; // do something with the next line }</font></pre>Similarly, you can use<samp><font color="0f0fff">new PrintStream(new FileOutputStream(<i>filename</i>))</font></samp>to write to a file.<a name="util"><h2> Other Goodies </h2></a><p>The library of pre-defined classes has several other handy tools.See<!WA25><!WA25><!WA25><!WA25><!WA25><!WA25><a href="http://www.cs.wisc.edu/~cs537-1/java/api">the online manual</a> for more details.<a name="wrappers"><h3>Integer, Character, etc.</h3></a>Java makes a big distinction between values (integers, characters, etc.)and objects.Sometimes you need an object when you have a value.The classes <samp><font color="0f0fff">Integer</font></samp>, <samp><font color="0f0fff">Character</font></samp>, etc. serve asconvenient wrappers for this purpose.For example, <samp><font color="0f0fff">Integer i = new Integer(3)</font></samp> creates a version ofthe number 3 wrapped up as an object.The value can be retrieved as <samp><font color="0f0fff">i.intValue</font></samp>.These classes also serve as convenient places to define utility functionsfor manipulating value of the given types, often as <samp><font color="0f0fff">static</font></samp> methodsor defined constants.<pre><font color="0f0fff"> Integer.MAX_VALUE // 2147483648, the largest possible int Integer.parseInt("123") // the int value 123 Integer.toHexString(123) // "7b", 123 in hex new Double("123e-2").doubleValue() // the double value 1.23 // see also page 150 of the Java Book Character.isDigit('3') // true Character.isUpperCase('a') // false Character.toUpperCase('a') // 'A'</font></pre><a name="vectors"><h3>Vector</h3></a><p>A <samp><font color="0f0fff">Vector</font></samp> is like an array, but it grows as necessary to allowyou to add as many elements as you like.Unfortunately, there is only one kind of <samp><font color="0f0fff">Vector</font></samp>--a vector of<samp><font color="0f0fff">Object</font></samp>. Thus you can insert objects of any type into it,but when you take objects out, you have to use a cast to recover theoriginal type.<pre><font color="0f0fff"> Vector v = new Vector(); // an empty vector for (int i=0; i<100; i++) v.addElement(new Integer(i)); // now it contains 100 Integer objects // print their squares for (int i=0; i<100; i++) { Integer N = (Integer)(v.elementAt(i)); int n = N.intvalue(); System.out.println(n*n); } v.setElementAt("hello", 5); // like v[5] = "hello" Object o = v.elementAt(3); // like o = v[3]; v.insertElement("world", 6); // set v[6] = "world" after first shifting // element v[7], v[8], ... to the right to make room v.removeElementAt(3); // remove v[3] and shift v[4], ... to the // left to fill in the gap</font></pre>The class <samp><font color="0f0fff">Vector</font></samp> is implemented using an ordinary array that isgenerally only partially filled.If <samp><font color="0f0fff">Vector</font></samp> runs out of space, it allocates a bigger array and copies overthe elements.There are a variety of additional methods, not shown here, thatlet you give the implementation advice on how to manage the extra spacemore efficiently.For example, if you know that you are not gonig to add any more elements to<samp><font color="0f0fff">v</font></samp>, you can call <samp><font color="0f0fff">v.trimToSize()</font></samp> to tell the system to repack the elements into an array just big enough to hold them.<p>Don't forget to <samp><font color="0f0fff">import java.util.Vector; </font></samp> (or <samp><font color="0f0fff">import java.util.*; </font></samp>) if you are using <samp><font color="0f0fff">Vectors</font></samp>.<h3>Hashtable</h3><p>A <samp><font color="0f0fff">Hashtable</font></samp> implements a mapping from objects called ``keys'' toobjects called ``values.''<pre><font color="0f0fff"> Hashtable h = new Hashtable(); // an empty table h.put("seven", new Integer(7)); // key is the String "seven"; // value is an Integer object Object o = h.put("seven", new Double(7.0)); // binds "seven" to a double object // and returns the previous value int n = ((Integer)o).intValue(); // n = 7 h.containsKey("seven") // true h.containsKey("twelve") // false o = h.get("seven"); // get current binding (a Double) o = h.remove("seven"); // get current binding and remove it h.clear(); // remove all bindings</font></pre><h3>StringTokenizer</h3><p>A <samp><font color="0f0fff">StringTokenizer</font></samp> is handy in breaking up a string into wordsseparated by white space (or other separator characters).The following example is from the Java book:<pre><font color="0f0fff"> String str = "Gone, and forgotten"; StringTokenizer tokens = new StringTokenizer(str, " ,"); while (tokens.hasMoreTokens()) System.out.println(tokens.nextToken());</font></pre>It prints out<pre><font color="0f0fff"> Gone and forgotten</font></pre>The second arguement to the constructor is a String containing thecharacters that such be considered separators (in this case, space andcomma). If it is omitted, it defaults to space, tab, return, and newline(the most common ``white-space'' characters).<p>There is a much more complicated class <samp><font color="0f0fff">StreamTokenizer</font></samp>for breaking up an<!WA26><!WA26><!WA26><!WA26><!WA26><!WA26><a href="#io">input stream</a> into tokens.Many of its features seem to be designed to aid in parsing the Javalangauge itself (which is not a surprise, considering that the Javacompiler is written in Java).<h3>Other Utilities</h3><p>The random-number generator
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -