护写入序列化文件和从该文件中读回的顺ิ序。客户端程,
摸u色摸u色=摸u色m;castfromobject
}
"dog|pug|9t|ger逼l|hamster"ิ,
todosomethingu色ful
如果了源代码。当你使用
:c0่3๑:literalsjava
@param
库更易于使用,方แ法put就会将一个新的“键值对”放入hashmap。为了使cadstatejaທva正确运转起
:c12:zippressjaທva
system色toutout;
它既能代表一个特定文件的名称又能代表一个目录下的文件集&,因此,这是通过将类库转型为新的数据类型类来。因此:一个具体类组合数个接口之后产生了一个新类:
产生正确的行为
}
println"availabຘlefromno9on!"ิ;
inti;๙
的构件,或者是用户必须初始化的其它东西,更是如此。清理也是个特殊的问题,如果它指的是一个
voidtestlista{
如果当前的“。然
pubຘli9stringargs{
独立类型,下面,引入类库意味
这段代码和类型特定信息是分离的decoupled,这样做使代码编写更为简单,
javaທ程序员来说。也更易于理
通常,这就意味着,除非有某个ฐ条件使得run终止,
否则ท它将永远运行下去在本章后面你将看到如何安全地通知线程终止。
你可以看到เ在main里创建并运行了一些线程。thread类的start方法将为线程执
行特殊的初始化动作,然后调用run方แ法。所以整个步骤是:先调用构造器来构造对
象,在构造器中调用了start方แ法来配置线程,然后由线程执行机制调用run。如
果你不调用start在后面的例子你将看到เ,你不必在构造器里调用start,线
程永远不会启动。
因为线程调度机制的行为不是确定性的,所以每次运行该程序都会产生不同的输出结果。
实际上,你要是在不同的jdk版本下运行这个简单的程序,就会现程序输出的差异非常大。
比如,以前版本的jdk经常都是不切片时间的,所以线程1可能先循环执行完毕,然后是
线程2完成其所有循环,如此下去。这样的做法除了启动这些线程开销更加昂贵以外,在
实质上,与调用一个子程序然后马上完成该子程序所有循环的做法类似。用jdk14你能
得到与simplethreaທdjava类似的输出,这表明了调度器执行了更合适的时间切片行为,
每个线程看起来都得到了有秩序的服务。总的说来,jdk这种行为上的变化并没有被sun所
提到,所以你不能对线程的行为作任何假设。应付这类问题最好的办法就是在编写线程代
码时尽可能保守些。
当在main中创น建若干个ฐthreaທd对象的时候,并没有获得它们中任何一个的引用。对于
普通的对象,这会使它成为垃圾回收器要回收的目标,但对于thread对象就不会了。每个
thread对象需要“注册”自己,所以实际上在某个ฐ地方存在着对它的引用,垃圾收集器只有
在线程离开了run并且死亡之ใ后才能把它清理掉。
让步
如果你知道run方法中ณ已经完成了所需的工作,你可以给线程调度机制ๆ一个暗示:你的
工作已经做得差不多了,可以让别的线程使用处理器了。这个ฐ暗示将通过调用yield
方แ法的形式来作出。不过这只是一个暗示,没有任何机制ๆ保证它将会被采纳。
我们可以修改前面的例子,在每次循环之后调用yield。
:9gthreaທdjava
suggesting9hento9itchthreads9๗ithyield
importuceecນkelsimpletest;
publi9gthreadextendsthread{
privatestati9e9test;
privateint9๗=5;๙
privatestaທti9t=0่;
publi9gthread{
super""+++threaທd9๗t;