小说迷-最新更新-java学习-java学习最新章节目录-第三卷 第一章
加入书签 | 推荐本书 | 返回书页 | 加入收藏

第三卷 第一章


    513  动  态  成  员  函  数  发  送  

当  你  用  点  操  作  符  调  用  一  个  对  象  实  例  的  成  员  函  数  时,  对  象  实  例  所  属  的  类  在  编  译  时  要  被  检  查,  以  确  保  调  用  的  成  员  函  数  在  该  类  中  是  存  在  的。  在  运  行  时,  对  象  实  例  可  以  指  向  所  声  明  类  型  的  子  类  的  实  例。  在  这  py;  情  况  下,  如  果  子  类  覆  盖  了  要  调  用  的  成  员  函  数,Java就  用  实  例  来  决  定  调  用  哪  一  个  成  员  函  数。  如  下  面  的  例  子,  两  个  类  是  子  类  和  超  类  的  关  系,  子  类  覆  盖  了  超  类  的  成  员  函  数。  

lass  A  {  vd  all(  )  {  Systtprntln(\"在A的all成  员  函  数  里\");  }  }  

lass  B  xtnds  A  {  vd  all(  )  {  Systtprntln(\"在B的all成  员  函  数  里\");  }  }  

lass  Dspath  {  pbl  stat  vd  an(Strng  args[])  {  A  a  =  nw  B(  );  aall(  );  }  }  

有  趣  的  是,  在  成  员  函  数an里,  我  们  把  变  量a声  明  为  类  型A,  然  后  把  类B的  一  个  实  例  存  放  到  它  上  面。  我  们  在a上  调  用  成  员  函  数all,Java编  译  器  确  定  在  类A确  实  有  成  员  函  数all,  但  是  在  运  行  时,  由  于a事  实  上  是B的  实  例,  所  以  调  用B的all,  而  不  调  用A的。  下  面  是  运  行  结  果:  C:\\>java  Dspath  在B的all成  员  函  数  里  

514  nal  

在  缺  省  情  况  下,  所  有  的  成  员  函  数  和  实  例  变  量  都  可  以  被  覆  盖。  如  果  你  希  望  你  的  变  量  或  成  员  函  数  不  再  被  子  类  覆  盖,  可  以  把  它  们  声  明  为nal。  这  意  味  着  将  来  的  实  例  都  依  赖  这  个  定  义。  例  如:  nal  nt  FILE_NEW  =  1;  nal  nt  FILE_OPEN  =  2;  nal  nt  FILE_SAVE  =  3;  anl  nt  FILE_SAVEAS  =  4;  nal  nt  FILE_QUIT  =  5;  nal变  量  用  大  写  标  识  符  是  一  个  一  般  的  约  定。  

515  静  态  

如  果  你  想  要  创  建  一  个  可  以  在  实  例  的  外  部  调  用  的  成  员  函  数,  那  么  你  只  需  声  明  它  为  静  态  的  (statpy;,  它  就  会  正  常  运  行。  静  态  成  员  函  数  只  能  直  接  调  用  其  他  静  态  成  员  函  数,  而  不  能  以  任  何  方  式  使  用ths或spr。  你  也  可  以  把  变  量  声  明  为  静  态  的。  如  果  你  想  初  始  化  一  个  静  态  变  量,  你  可  以  用  stat声  明  一  个  恰  好  在  类  调  用  时  执  行  一  次  的  程  序  块。  下  面  的  例  子  是  一  个  带  有  一  个  静  态  成  员  函  数,  几  个  静  态  变  

量,  和  一  个  静  态  初  始  块  的  类。  

lass  Stat  {  stat  nt  a  =  3;  stat  nt  b;  stat  vd  thd(nt  x){  Systtprntln(\"x  =  \"  +  x);  Systtprntln(\"a  =  \"  +  a);  Systtprntln(\"b  =  \"  +  b);  }  stat  {  Systtprntln(\"静  态  初  始  块\");  b  =  a    4;  }  pbl  stat  vd  an(Strng  args[])  {  thd(42);  }  }  这  个  类  被  调  用,  所  有  的  静  态  变  量  都  被  初  始  化,a被  赋  为3,  然  后  运  行stat块,  这  将    印  出  一  段  消  息,  并  且  把b赋  为a4,  即12。  然  后  解  释  器  调  用an成  员  函  数,  它  调  用  了  成  员  函  数  thd,  参  数x为42。  这  三  个prntln语  句    印  了  两  个  静  态  变  量a、b和  局  部  变  量x。  下  面  是  运  行  结  果:  C:\\>java  Stat  静  态  初  始  块  x  =  42  a  =  3  b  =  12  一  个  静  态  成  员  函  数  可  以  通  过  它  所  属  的  类  名  来  调  用。  象  调  用  实  例  变  量  一  样,  你  可  以  用  点  操  作  符  通  过  类  名  来  调  用  静  态  成  员  函  数  和  静  态  变  量。Java就  是  这  样  实  现  了  全  局  函  数  和  全  局  变  量。  下  面  的  例  子  里,  我  们  创  建  了  带  有  一  个  静  态  成  员  函  数  和  两  个  静  态  变  量  的  类。  第  二  个  类  可  以  通  过  名  字  直  接  来  调  用  第  一  个  类  的  静  态  成  员  函  数  和  静  态  变  量。  

lass  statClass  {  stat  nt  a  =  42;  stat  nt  b  =  99;  stat  vd  

all(  )  {  Systtprntln(\"a  =  \"  +  a);  }  }  

lass  StatByNa  {  pbl  stat  vd  an(Strng  args[])  

{  StatClassall(  );  Systtprntln(\"b  =  \"  +  statClassb);  }  }  

下  面  是  运  行  结  果:  C:\\>java  statByNa  a  =  42  b  =  99  

516  抽  象  

有  时  你  需  要  定  义  一  个  给  出  抽  象  结  构、  但  不  给  出  每  个  成  员  函  数  的  完  整  实  现  的  类。  如  果  某  个  成  员  函  数  没  有  完  整  实  现,  必  须  要  由  子  类  来  覆  盖,  你  可  把  它  声  明  为  抽  象(abstratpy;  型。  含  有  抽  象  型  成  员  函  数  的  类  必  须  声  明  为  抽  象  的。  为  了  把  一  个  类  声  明  为  抽  象  的,  你  只  需  在  类  定  义  的lass关  键  词  前  放  置  关  键  词abstrat。  这  py;  类  不  能  直  接  用nw操  作  符  生  成  实  例,  因  为  它  们  的  完  整  实  现  还  没  有  定  义。  你  不  能  定  义  抽  象  的  构  造  函  数  或  抽  象  的  静  态  成  员  函  数。  抽  象  类  的  子  类  或  者  实  现  了  它  的  超  类  的  所  有  抽  象  的  成  员  函  数,  或  者  也  被  声  明  为  抽  象  的。  下  面  例  子  是  一  个  带  有  抽  象  成  员  函  数  的  类,  其  后  是  一  个  实  现  了  该  成  员  函  数  的  类。  

abstrat  lass  A  {  abstrat  vd  all(  )  ;  vd  t(  )  {  systtprntln(\"在A的t成  员  函  数  里\");  }  }  lass  B  xtnds  A  {  vd  all(  )  {  Systtprntln(\"在B的all成  员  函  数  里\");  }  }  lass  Abstrat  {  pbl  stat  vd  an(Strng  args[])  {  A  a  =  nw  B(  );  

aall(  );  at(  );  }  }  

下  面  是  运  行  结  果:  C:\\>java  Abstrat  在B的all成  员  函  数  里  在A的t成  员  函  数  里  

本  章  小  结  

1  类  是Java语  言  面  向  对  象  编  程  的  基  本  元  素,  它  定  义  了  一  个  对  象  的  结  构  和  功  能。  2  Java通  过  在  类  定  义  的  大  括  号  里  声  明  变  量  来  把  数  据  封  装  在  一  个  类  里,  这  里  的  变  量  称  为  实  例  变  量。  3  成  员  函  数,  是  类  的  功  能  接  口,  是  类  定  义  里  的  一  个  子  程  序,  在  类  的  定  义  里  和  实  例  变  量  处  于  同  一  级  别。

第  六  章  Java图  形  用  户  接  口  

对  一  个  优  秀  的  应  用  程  序  来  说,  良  好  的  图  形  用  户  接  口  是  必  不  可  少  的。  缺  少  良  好  的  图  形  用  户  接  口,  将  会  给  用  户  理  解  和  使  用  应  用  程  序  带  来  很  多  不  便。  很  难  想  象  用  户  为  了  学  会  使  用  一  个  应  用  程  序,  去  记  一  大  堆  命  令。  Java提py;  了  生  成  一  个  良  好  的  图  形  用  户  接  口  所  需  要  的  一py;  基  本  元  件:  面  板(Panl  py;、  按  钮  (Bttn  py;、  标py;(Labl  py;、  画  板(Canvass  py;、  滚  动  条(Srllbar  py;、  列  表  框(Lst  py;、  文  本  域(Txt  Fld  py;、  文  本  区(Txt  Ara  py;。  

61  面  板  

面  板  提py;  了  建  立  应  用  程  序  的  空  间。  你  可  以  把  图  形  元  件(包  括  其  他  面  板  py;  放  在  一  个  面  板  上。  Applt类  提py;  了  一  个  基  本  的  面  板。  

611  布  局  管  理  

Java提py;  了  几  种  布  局:  顺  序  布  局(Flw  Layt  py;、  边  界  布  局(Brdr  Layt  py;  和  网  格  布  局  (Grd  Layt)

6111  顺  序  布  局  

顺  序  布  局(Flw  Layt  py;  是  最  基  本  的  一  种  布  局,  面  板  的  缺  省  布  局  就  是  顺  序  布  局。  顺  序  布  局  指  的  是  把  图  形  元  件  一  个  接  一  个  地rg;  平  地  放  在  面  板  上。  下  面  是  一  个  顺  序  布  局  的  例  子:  

prt  javaawt;  prt  javaappltApplt;  

pbl  lass  yBttns  xtnds  Applt  {  Bttn  bttn1,  bttn2,  bttn3;  

pbl  vd  nt()  {  bttn1  =  n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n3);  }  }  

6112  边  界  布  局  

边  界  布  局  包  括  五  个  区:  北  区、  南  区、  东  区、  西  区  和  中  区。  这  几  个  区  在  面  板  上  的  分  布  规  律  是\"  上  北  下  南,  左  西  右  东\"。  下  面  是  一  个  边  界  布  局  的  例  子:  

prt  javaawt;  prt  javaappltApplt;  

pbl  lass  bttnDr  xtnds  Applt  {  Bttn  bttnN,  bttnS,  bttnW,  bttnE,  bttnC;  

pbl  vd  nt()  {  stLayt(n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷nC);  }  }  

6113  网  格  布  局

网  格  布  局  把  面  板  分  成  一  个  个  的  网  格,  你  可  以  给  出  网  格  的  行  数  和  列  数。  下  面  是  一  个  网  格  布  局  的  例  子:  

prt  javaawt;  prt  javaappltApplt;  

pbl  lass  bttnGrd  xtnds  Applt  {  Bttn  bttn1,  bttn2,  bttn3,  bttn4,  bttn5,  bttn6,  bttn7,  bttn8;  

pbl  vd  nt()  {  stLayt(n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n(\"艮\");  

bttn4  =  n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n(\"兑\");  

add(bttn1);  add(bttn2);  add(bttn3);  add(bttn4);  add(bttn5);  add(bttn6);  add(bttn7);  add(bttn8);  }  }  

62  按  钮  

621  按  钮  事  件

用  户  点  一  下  按  钮,  就  会  有  一  个  按  钮  事  件  发  生。  你  可  以  通  过  覆  盖  一  个applt的atn成  员  函  数  来  捕  捉  按  钮  事  件。  pbl  blan  atn  (Evnt  ,  Objt  )  {    (targt  nstan  Bttn)  {  systtprntln  ((strng)  );  }  ls  {  Systtprntln  (\"Nn-bttn  vnt\");  }  rtrn  tr;  }  

622  按  钮  类  型  

Java提py;  了  标  准  的  按  压  式  按  钮,  同  时  也  提py;  了  选  择  式  按  钮  和  标  记  式  按  钮。  

6221  选  择  式  按  钮  

选  择  式  按  钮  提py;  了  从  几  个  选  项  中  选  一  个  选  项  的  功  能。  下  面  是  从  几  个  市  中  选  一  个  市  的  例  子,  市  名  放  在  选  择  式  按  钮  中:  

CtyChsr  =  nw  Ch();  

CtyChsraddIt(\"北py;\");  CtyChsraddIt(\"上海\");  

CtyChsraddIt(\"天  津\");  

add(CtyChsr);  

6222  标  记  式  按  钮

标  记  式  按  钮  的  状  态  作  为  标  记  框  事  件  的  对  象  参  数  返  回。  下  面  是  一  个  标  记  式  按  钮  的  例  子:  

Chbx  llStylBttn;  llStylBttn  =  nw  Chbx(\"Sld\");  

pbl  blan  atn(Evnt  ,  Objt  arg)  {    (targt  nstan  

Chbx)  {  Systtprntln(\"Chbx:  \"  +  arg);  }  rtrn  tr;  }  

6223  按  键  式  按  钮

按  键  式  按  钮  是  一  组  按  钮,  用  户  可  以  选  中  其  中  一  个,  同  时  这  一  组  中  的  其  他  按  钮  将  被  关  闭。  下  面  是  一  个  按  键  式  按  钮  的  例  子:  pbl  lass  ChBx  xtnds  Applt  {  ChbxGrp  bg;  pbl  vd  nt()  {  bg  =  n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hr\",  bg,  als));  }  }  

623  自  包  含  按  钮  

Java语  言  的  面  向  对  象  特  性  使  我  们  能  够  创  建  完  全  自  包  含  的  按  钮。  在  自  包  含  按  钮  里,  你  可  以  在py;  展  按  钮  类  里  建  立  事  件  控  制  函  数。  下  面  是  一  个  自  包  含  按  钮  的  例  子:  

prt  javaawt;  prt  javaappltApplt;  

lass  Bttn  xtnds  Bttn  {  

pbl  Bttn()  {  stLabl(\"O\");  }  

pbl  blan  atn(Evnt  ,  Objt  arg)  

{  Systtprntln(\"OKBttn\");  rtrn  tr;  }  }  

pbl  lass  bttntst  xtnds  Applt  {  Bttn  yOBttn;  

pbl  vd  nt()  {  yOBttn  =  nw  Bttn();  add(yOBttn);  }  }  

63  标py;  

标py;  是  一  种  放  到  面  板  上  的  静  止  的  正  文。  下  面  是  一  个  标py;  的  例  子:  prt  javaa由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷CENTER,  10,  10));  Labl  labl1  =  nw  Labl(\"你  好!\");  Labl  labl2  =  nw  Labl(\"另  一  个  标py;\");  add(labl1);  add(labl2);  }  }  

64  列  表  框  

列  表  框  使  用  户  易  于  操  作  大  量  的  选  项。  创  建  列  表  框  的  方  法  和Ch  bttn有py;  相  似。  列  表  框  的  所  有  条  目  都  是  可  见  的,  如  果  选  项  很  多,  超  出  了  列  表  框  可  见  区  的  范  围,  则  列  表  框  的  旁  边  将  会  有  一  个  滚  动  条。  首  先,  创  建  列  表  框:  Lst  l  =  nw  Lst(4,  als);  这  个  成  员  函  数  创  建  了  一  个  显  示4行  的  列  表  框。  第  二  个  参  数\"als\"表  示  这  个  列  表  框  是  单  选  的,  如  果  是\"tr  \",  则  表  示  是  多  选  的。  下  面  增  加  列  表  框  的  选  项:  laddIt(\"北py;  大  学\");  laddIt(\"清  华  大  学\");  laddIt(\"吉林  大  学\");  laddIt(\"复py;  大  学\");  laddIt(\"南  开  大  学\");  laddIt(\"天  津  大  学\");  laddIt(\"南py;  大  学\");  add(l);  

641  在  列  表  框  中  进  行  选  择  

可  以  用  成  员  函  数gtSltdIt()或gtSltdIts()来  接  收  在  列  表  框  中  被  选  的  选  项。  在  单  选  列  表  框  里,\"  双  击\"  一  个  选  项  就  可  以  触  发  一  个  可  被atn()成  员  函  数  捕  捉  到  的  事  件。  pbl  blan  atn(Evnt  ,  Objt  arg)  {          (targt  nstan  Lst)  {  Systtprntln(\"Lst  ntry:\"  +  arg);  }        }  

642  多  选  列  表  框

对  于  多  选  列  表  框,  要  使  你  的  选  择  产  生  作  用,  需  要  使  用  其  他  的  外  部  事  件。  例  如,  你  可  以  使  用  按  钮  事  件:  pbl  blan  atn(Evnt  ,  Objt  arg)  {          (targt  nstan  Bttn)  {          (\"O\"qals(arg))  {  strng[]  sltd  ;  sltd  =  lgtSltdIts(  );  r  (nt  I  =  0;  I<  sltdlngth;  I++)  {Systtprntln(sltd[]);  }  }  }  }  

65  文  本  域  

文  本  域  一  般  用  来  让  用  户  输  入  象  姓  名、  信  用  卡  号  这  样  的  信  息,  它  是  一  个  能  够  接  收  用  户  的  键  盘  输  入  的  小  块  区  域。  

651  创  建  文  本  域  

在  创  建  文  本  域  时,  有  四  种  类  型py;  你  选  择:  空  的、  空  的  并  且  具  有  指  定  长  度、  带  有  初  始  文  本  内  容  的  和  带  有  初  始  文  本  内  容  并  具  有  指  定  长  度  的。  下  面  是  生  成  这  四  种  文  本  域  的  代  码:  TxtFld  t1,  t2,  t3,  t4;  //  空  的  文  本  域  t1  =  nw  TxtFld()  ;  //  长  度  为20的  空  的  文  本  域  t2  =  nw  TxtFld(20)  ;  //  带  有  初  始  文  本  内  容  的  文  本  域  t3  

=  nw  TxtFld(\"你  好\")  ;  //  带  有  初  始  文  本  内  容  并  具  有  指  定  长  度  的  文  本  域  t4  =  nw  TxtFld(\"你  好\",  30)  ;  add(t1)  ;  add(t2)  ;  add(t3)  ;  add(t4)  ;  

652  文  本  域  事  件  

当  用  户  在  文  本  域  里  敲\"  回  车\"  键  时,  就  产  生  了  一  个  文  本  域  事  件。  象  其  他  事  件  一  样,  你  可  以  以  在  成  员  函  数atn()中  捕  捉  到  这  个  事  件。  

pbl  blan  atn(Evnt  ,  Objt  arg)  {          (targt  nstan  TxtFld)  {  Systtprntln(\"TxtFld:  \"+arg);  }        }  

66  文  本  区  

文  本  区  可  以  显  示  大  段  的  文  本。  

661  创  建  文  本  区

与  文  本  域  类  似,  创  建  文  本  区  时  也  有  四  种  类  型py;  选  择,  但  如  果  指  定  文  本  区  的  大  小,  必  须  同  时  指  定  行  数  和  列  数。  TxtAra  ta1,  ta2;  //  一  个  空  的  文  本  区  ta1  =  nw  TxtAra();  //  一  个  带  有  初  始  内  容、  大  小  为5  x  40  的  文  本  区  ta2  =  nw  TxtAra(\"你  好!\",  5,  40);  

可  以  用  成  员  函  数stEdtabl()来  决  定  用  户  是  否  可  对  文  本  区  的  内  容  进  行  编  辑。  //  使  文  本  区  为  只  读  的  ta2stEdtabl(als)  

662  接  收  文  本  区  的  内  容

可  以  用  成  员  函  数gtTxt()来  获  得  文  本  区  的  当  前  内  容。  例  如:  Systtprntln(ta1gtTxt());  文  本  区  本  身  不  产  生  自  己  的  事  件。  但  你  可  以  用  外  部  事  件  来  接  收  文  本  区  的  内  容:  pbl  blan  atn(Evnt  ,  Objt  )  {    (targt  nstan  Bttn)  {    (\"snd\"qals())  {  Strng  txtTSnd  =  ta1gtTxt  ();  

Systtprntln(\"sndng:  \"  +  txtTsnd);  

ySndFntn(txtTSnd);  }  }  ls  {        }  }  

67  画  板

画  板  能  够  捕  捉  到py;  露  事  件、  鼠  标  事  件  和  其  他  类  似  的  事  件。  基  本  的  画  板  类  不  处  理  这py;  事  件,  但  你  可  以py;  展  它  来  创  建  有  你  所  需  功  能  的  画  板  类。  

671  创  建  画  板  

prt  javaawt;  prt  javaappltApplt;  

pbl  lass  sprGUI  xtnds  Applt  {        yCanvas  ddl;        pbl  

vd  nt()  {        //  建  立  我  们  的  画  板  ddl  =  nw  yCanvas();  

ddlrshap(0,  0,  100,  100);  ltPanladd(\"Cntr\",ddl);        }  }  

lass  yCanvas  xtnds  Canvas  {  pbl  vd  pant(Graphs  g)  

{  gdrawRt(0,  0,  99,  99);  gdrawStrng(\"Canvas\",  15,  40);  }  }  

672  画  板  事  件  

你  可  以  覆  盖  一  般  的  事  件  处  理  成  员  函  数。  下  面  是  一  个  包  含  了sDwn事  件  处  理  的  例  子:  prt  javaawt;  prt  javaappltApplt;  

pbl  lass  anvas  xtnds  Applt  {  

Bttn  b1;  

pbl  vd  nt()  {  //  St  r  layt  as  a  Brdr  styl  stLayt(nw  

BrdrLayt(15,  15));  b1  =  nw  Bttn(\"Tst\");  yCanvas  1  =  nw  

yCanvas(100,  100);  //  add  th  anvas  and  th  bttn  t  th  applt  

add(\"Cntr\",  1);  add(\"Sth\",  b1);  }  

pbl  blan  atn(Evnt  ,  Objt  arg)  {  Systtprntln(\"Evnt:  

\"  +  arg);  rtrn  tr;  }  

pbl  blan  sDwn(Evnt  ,  nt  x,  nt  y)  

{  Systtprntln(\"Ms  wrs:  (\"  +  x  +  \",\"  +  y  +  \")\");  rtrn  tr;  }  }  

lass  yCanvas  xtnds  Canvas  {  prvat  nt  wdth;  prvat  nt  hght;  

pbl  yCanvas(nt  由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷  =  h;  rshap(0,  0,  w,  

h);  }  

pbl  vd  pant(Graphs  g)  {  gstClr(Clrbl);  gllRt(0,  0,  

wdth,  hght);  }  

pbl  blan  sDwn(Evnt  ,  nt  x,  nt  y)  {    ((  x  <  wdth)  &&  (y  

第  七  章  多  线  程

71  多  线  程  的  概  念  

多  线  程  编  程  的  含  义  是  你  可  将  程  序  任  务  分  成  几  个  并  行  的  子  任  务。  特  别  是  在  网  络  编  程  中,  你  会  发  现  很  多  功  能  是  可  以  并  发  执  行  的。  比  如  网  络  传  输  速  度  较  慢,  用  户  输  入  速  度  较  慢,  你  可  以  用  两  个  独  立  的  线  程  去  完  成  这  py;  功  能,  而  不  影  响  正  常  的  显  示  或  其  他  功  能。  多  线  程  是  与  单  线  程  比  较  而  言  的,  普  通  的WINDOWS采  用  单  线  程  程  序  结  构,  其  工  作  原  理  是:  主  程  序  有  一  个  消  息  循  环,  不  断  从  消  息  队  列  中  读  入  消  息  来  决  定  下  一  步  所  要  干  的  事  情,  一  般  是  一  个  子  函  数,  只  有  等  这  个  子  函  数  执  行  完  返  回  后,  主  程  序  才  能  接  收  另  外  的  消  息  来  执  行。  比  如  子  函  数  功  能  是  在  读  一  个  网  络  数  据,  或  读  一  个  文  件,  只  有  等  读  完  这  py;  数  据  或  文  件  才  能  接  收  下  一  个  消  息。  在  执  行  这  个  子  函  数  过  程  中  你  什  么  也  不  能  干。  但  往  往  读  网  络  数  据  和  等  待  用  户  输  入  有  很  多  时  间  处  于  等  待  状  态,  多  线  程  利  用  这  个  特  点  将  任  务  分  成  多  个  并  发  任  务  后,  就  可  以  解  决  这  个  问  题。  

711  Java线  程  的  模  型  

Java的  设  计  思  想  是  建  立  在  当  前  大  多  数  操  作  系  统  都  实  现  了  线  程  调  度。Java虚  拟  机  的  很  多  任  务  都  依  赖  线  程  调  度,  而  且  所  有  的  类  库  都  是  为  多  线  程  设  计  的。  实  时  上,Java支  持Mantsh和Ms-ds  的  平  台  rg;  所  以  迟  迟  未  出  来  就  是  因  为  这  两  个  平  台  都  不  支  持  多  线  程。Java利  用  多  线  程  实  现  了  整  个  执  行  环  境  是  异  步  的。  在Java程  序  里  没  有  主  消  息  循  环。  如  果  一  个  线  程  等  待  读  取  网  络  数  据,  它  可  以  运  行  但  不  停  止  系  统  的  其  他  线  程  执  行。  用  于  处  理  用  户  输  入  的  线  程  大  多  时  间  是  等  待  用  户  敲  键  盘  或  击  鼠  标。  你  还  可  以  使  动  画  的  每  一  帧  rg;  间  停  顿  一  秒  而  并  不  使  系  统  暂  停。  一  py;  线  程  启  动  后,  它  可  以  被  挂  起,  暂  时  不  让  它  执  行。  挂  起  的  线  程  可  以  重  新  恢  复  执  行。  任  何  时  间  线  程  都  可  以  被  停  止,  被  停  止  的  线  程  就  不  能  再  重  新  启  动。  Java语  言  里,  线  程  表  现  为  线  程  类,  线  程  类  封  装  了  所  有  需  要  的  线  程  操  作  控  制。  在  你  心  里,  必  须  很  清  晰  地  区  分  开  线  程  对  象  和  运  行  线  程,  你  可  以  将  线  程  对  象  看  作  是  运  行  线  程  的  控  制  面  板。  在  线  程  对  象  里  有  很  多  函  数  来  控  制  一  个  线  程  是  否  运  行,  睡  眠,  挂  起  或  停  止。  线  程  类  是  控  制  线  程  行  为  的  唯  一  的    段。  一  py;  一  个Java程  序  启  动  后,  就  已  经  有  一  个  线  程  在  运  行。  你  可  通  过  调  用ThradrrntThrad  函  数  来  查  看  当  前  运  行  的  是  哪  一  个  线  程。  

你  得  到  一  个  线  程  的  控  制  柄,  你  就  可  以  作  很  有  趣  的  事  情,  即  使  单  线  程  也  一  样。  下  面  这  个  例  子  让  你  知  道  怎  样  操  纵  当  前  线  程。  Flna:tstthrad  

lass  tstthrad  {  pbl  stat  vd  an(Strng  args[])  {  Thrad  t  

=ThradrrntThrad();  tstNa(\"Ths  Thrad  s  rnnng\");  

Systtprntln(\"Th  rnnng  thrad:\"  +  t);  try  {  r  (nt  =0;<5;++)  

{  Systtprntln(\"Slp  t  \"+);  Thradslp(1000);  }  

}  ath  (IntrrptdExptn  )  {Systtprntln(\"thrad  has  wrng\");  }  

}  }  

执  行  结  果:java  tstthrad  Th  rnnng  thrad:Thrad[Ths  Thrad  s  rnnng,5,an]  Slp  t  0  Slp  t  1  Slp  t  2  Slp  t  3  Slp  t  4  

712  启  动  接  口

一  个  线  程  并  不  激  动  人  心,  多  个  线  程  才  有  实  际  意  义。  我  们  怎  样  创  建  更  多  的  线  程  呢?  我  们  需  要  创  建  线  程  类  的  另  一  个  实  例。  当  我  们  构  造  了  线  程  类  的  一  个  新  的  实  例,  我  们  必  须  告  诉  它  在  新  的  线  程  里  应  执  行  哪  一  段  程  序。  你  可  以  在  任  意  实  现  了  启动  接  口  的  对  象  上  启  动  一  个  线  程。  启  动  接  口  是  一  个  抽  象  接  口,  来  表  示  本  对  象  有  一  py;  函  数  想  异  步  执  行。  要  实  现  启  动  接  口,  一  个  类  只  需  要  有  一  个  叫rn的  函  数。  下  面  是  创  建  一  个  新  线  程  的  例  子:  

Flna:twthradjava  

lass  twthrad  plnts  Rnnabl  {  twthrad()  {  Thrad  t1  

=ThradrrntThrad();  t1stNa(\"Th  rst  an  thrad\");  

Systtprntln(\"Th  rnnng  thrad:\"  +  t1);  Thrad  t2  =  nw  

Thrad(ths,\"th  snd  thrad\");  Systtprntln(\"rat  anthr  

thrad\");  t2start();  try  {  Systtprntln(\"rst  thrad  wll  

slp\");  Thradslp(3000);  }ath  (IntrrptdExptn  )  

{Systtprntln(\"rst  thrad  has  wrng\");  }  

Systtprntln(\"rst  thrad  xt\");  }  pbl  vd  rn()  {  try  {  r  

(nt  =0;<5;++)  {  Systtprntln(\"Slp  t  r  thrad  2:\"+);  

Thradslp(1000);  }  

}  ath  (IntrrptdExptn  )  {Systtprntln(\"thrad  has  

wrng\");  }  

Systtprntln(\"snd  thrad  xt\");  }  pbl  stat  vd  

an(Strng  args[])  {  nw  twthrad();  }  }  

执  行  结  果:java  twthrad  

Th  rnnng  thrad:Thrad[Th  rst  an  thrad,5,an]  rat  anthr  

thrad  rst  thrad  wll  slp  Slp  t  r  thrad  2:0  Slp  t  r  

thrad  2:1  Slp  t  r  thrad  2:2  rst  thrad  xt  Slp  t  r  

thrad  2:3  Slp  t  r  thrad  2:4  snd  thrad  xt  

an线  程  用nw  Thrad(ths,  \"th  snd  thrad\")创  建  了  一  个Thrad对  象,  通  过  传  递  第  一  个  参  数  来  标  明  新  线  程  来  调  用ths对  象  的rn函  数。  然  后  我  们  调  用start函  数,  它  将  使  线  程  从rn函  数  开  始  执  行。  

713  同  步  

因  为  多  线  程  给  你  提  py;  了  程  序  的  异  步  执  行  的  功  能,  所  以  在  必  要  时  必  须  还  提  py;  一  种  同  步  机  制。  例  如,  你  想  两  个  线  程  通  讯  并  共  享  一  个  复  杂  的  数  据  结  构,  你  需  要  一  种  机  制  让  他  们  相  互  牵  制  并  正  确  执  行。  为  这  个  目  的,Java用  一  种  叫  监  视  器(ntr)的  机  制  实  现  了  进  程  间  的  异  步  执  行。  可  以  将  监  视  器  看  作  是  一  个  很  小  的  盒  子,  它  只  能  容  纳  一  个  线  程。  一  py;  一  个  线  程  进  入  一  个  监  视  器,  所  有  其  他  线  程  必  须  等  到  第  一  个  线  程  退  出  监  视  器  后  才  能  进  入。  这  py;  监  视  器  可  以  设  计  成  保  护  共  享  的  数  据  不  被  多  个  线  程  同  时  操  作。  大  多  数  多  线  程  系  统  将  这  py;  监  视  器  设  计  成  对  象,Java提  py;  了  一  种  更  清  晰  的  解  决  方  案。  没  有Mntr类;  每  个  对  象  通  过  将  他  们  的  成  员  函  数  定  义  成synhrnzd来  定  义  自  己  的  显  式  监  视  器,  一  py;  一  个  线  程  执  行  在  一  个synhrnzd函  数  里,  其  他  任  何  线  程  都  不  能  调  用  同  一  个  对  象  的  

synhrnzd函  数。  

714  消  息  

你  的  程  序  被  分  成  几  个  逻  辑  线  程,  你  必  须  清  晰  的  知  道  这  py;  线  程  rg;  间  应  怎  样  相  互  通  讯。Java  提  了wat和nty等  功  能  来  使  线  程  rg;  间  相  互  交  谈。  一  个  线  程  可  以  进  入  某  一  个  对  象  的synhrnzd  函  数  进  入  等  待  状  态,  直  到  其  他  线  程  显  式  地  将  它  唤  醒。  可  以  有  多  个  线  程  进  入  同  一  个  函  数  并  等  待  同  一  个  唤  醒  消  息。  

72  Java线  程  例  子  

721  显  式  定  义  线  程  

在  我  们  的  单  线  程  应  用  程  序  里,  我  们  并  没  有  看  见  线  程,  因  为Java能  自  动  创  建  和  控  制  你  的  线  程。  如  果  你  使  用  了  理  解Java语  言  的  浏  览  器,  你  就  已  经  看  到  使  用  多  线  程  的Java程  序  了。  你  也  许  注  意  到  两  个  小  程  序  可  以  同  时  运  行,  或  在  你  移  动  滚  动  条  时  小  程  序  继  续  执  行。  这  并  不  是  表  明  小  程  序  是  多  线  程  的,  但  说  明  这  个  浏  览  器  是  多  线  程  的。  多  线  程  应  用  程  序(或applt)可  以  使  用  好  几  个  执  行  上  下  文  来  完  成  它  们  的  工  

作。  多  线  程  利  用  了  很  多  任  务  包  含  单  独  的  可  分  离  的  子  任  务  的  特  点。  每  一  个  线  程  完  成  一  个  子  任  务。  但  是,  每  一  个  线  程  完  成  子  任  务  时  还  是  顺  序  执  行  的。  一  个  多  线  程  程  序  允  许  各  个  线  程尽快  执  行  完  它  们。  这  种  特  点  会  有  更  好  的  实  时  输  入  反  应。  

722  多  线  程  例  子

下  面  这  个  例  子  创  建  了  三  个  单  独  的  线  程,  它  们  分  别    印  自  己  的\"Hll  Wrld\":  

//Dn  r  spl  thradsThy  wll  pas  r  a  shrt  t  //and  thn  

prnt  t  thr  nas  and  dlay  ts  lass  TstThrad  xtnds  Thrad  

{  prvat  Strng  wha;  prvat  nt  dlay;  

//Or  nstrtr  t  str  th  na  (wha)  //and  t  t  slp  (dlay)  

pbl  TstThrad(Strng  s,  nt  d)  {  wha  =  s;  dlay  =  d;  }  

//Rn  -  th  thrad  thd  slar  t  an()  //Whn  rn  s  nshd,  th  

thrad  ds  //Rn  s  alld  r  th  start()  thd    Thrad  pbl  vd  

rn()  {  //Try  t  slp  r  th  spd  t  try  {  slp(dlay);  }  

ath(IntrrptdExptn  )  {}  //Nw  prnt  t  r  na  

Systtprntln(\"Hll  Wrld!\"+wha+\"\"+dlay);  }  }  /    Mlttst  

A  spl  ltthrad  thst  prgra  /  pbl  lass  lttst  {  pbl  

stat  vd  an(Strng  args[])  {  TstThrad  t1,t2,t3;  //Crat  r  tst  

thrads  t1  =  nw  TstThrad(\"Thrad1\",(nt)(Mathrad()2000));  t2  =  

nw  TstThrad(\"Thrad2\",(nt)(Mathrad()2000));  t3  =  nw  

TstThrad(\"Thrad3\",(nt)(Mathrad()2000));  

//Start  ah    th  thrads  t1start();  t2start();  t3start();  }  }  

723  启  动  一  个  线  程  

程  序  启  动  时  总  是  调  用an()函  数,  因  此an()是  我  们  创  建  和  启  动  线  程  的  地  方:  

t1  =  nw  TstThrad(\"Thrad1\",(nt)(Mathrad()2000));  

这  一  行  创  建  了  一  个  新  的  线  程。  后  面  的  两  个  参  数  传  递  了  线  程  的  名  称  和  线  程  在    印  信  息  rg;  前  的  延  时  时  间。  因  为  我  们  直  接  控  制  线  程,  我  们  必  须  直  接  启  动  它:  t1start();  

724  操  作  线  程  

如  果  创  建  线  程  正  常,t1应  包  含  一  个  有  效  的  执  行  线  程。  我  们  在  线  程  的rn()函  数  里  控  制  线  程。  一  py;  我  们  进  入rn()函  数,  我  们  便  可  执  行  里  面  的  任  何  程  序。rn()好  象an()一  样。  

rn()  执  行  完,  这  个  线  程  也  就  结  束  了。  在  这  个  例  子  里,  我  们  试  着  延  迟  一  个  随  机  的  时  间(通  过  参  数  传  递)  slp(dlay);  

slp()函  数  只  是  简  单  地  告  诉  线  程  休  息  多  少  个  毫  秒  时  间。  

如  果  你  想  推  迟  一  个  线  程  的  执  行,  你  应  使  用slp()函  数。  当  线  程  睡  眠  是slp()并  不  占  用  系  统  资  源。  其  它  线  程  可  继  续  工  作。  一  py;  延  迟  时  间  完  毕,  它  将    印\"Hll  Wrld\"和  线  程  名  称  及  延  迟  时  间。  

725  暂  停  一  个  线  程

我  们  经  常  需  要  挂  起  一  个  线  程  而  不  指  定  多  少  时  间。  例  如,  如  果  你  创  建  了  一  个  含  有  动  画  线  程  的  小  程  序。  也  许  你  让  用  户  暂  停  动  画  至  到  他  们  想  恢  复  为  止。  你  并  不  想  将  动  画  线  程  仍  调,  但  想  让  它  停  止。  象  这  种  类  似  的  线  程  你  可  用sspnd()函  数  来  控  制:  t1sspnd();  这  个  函  数  并  不  永  久  地  停  止  了  线  程,  你  还  可  用rs()函  数  重  新  激  活  线  程:  t1rs();  

726  停  止  一  个  线  程  

线  程  的  最  后  一  个  控  制  是  停  止  函  数stp()。  我  们  用  它  来  停  止  线  程  的  执  行:  t1stp();  

注  意:  这  并  没  有  消  灭  这  个  线  程,  但  它  停  止  了  线  程  的  执  行。  并  且  这  个  线  程  不  能  用t1start()重  新  启  动。  在  我  们  的  例  子  里,  我  们  从  来  不  用  显  式  地  停  止  一  个  线  程。  我  们  只  简  单  地  让  它  执  行  完  而  已。  很  多  复  杂  的  线  程  例  子  将  需  要  我  们  控  制  每  一  个  线  程。  在  这  种  情  况  下  会  使  用  到stp()函  数。  如  果  需  要,  你  可  以  测  试  你  的  线  程  是  否  被  激  活。  一  个  线  程  已  经  启  动  而  且  没  有  停  止  被  认  为  是  激  活  的。  t1sAlv()  如  果t1是  激  活  的,  这  个  函  数  将  返  回tr  

727  动  画  例  子  

下  面  是  一  个  包  含  动  画  线  程  的applt例  子:  

prt  javaawt;  prt  javaawtagIagPrdr;  prt  

javaappltApplt;  

pbl  lass  atst3  xtnds  Applt  plnts  Rnnabl  {  Iag  ags[];  

MdaTrar  trar;  nt  ndx  =  0;  Thrad  anatr;  

nt  axWdth,axHght;  //Or  -srn  pnnts  r  dbl  brng  

Iag  SrIag;  Graphs  SrGC;  

//Can  w  pant  ys  blan  ladd  =  als;  

//Intalz  th  applt  St  r  sz  and  lad  th  ags  pbl  vd  nt()  

[  //St  p  r  ag  ntr  trar  =  nw  MdaTrar(ths);  

//St  th  sz  and  wdth    r  applt  axWdth  =  100;  axHght  =100;  

ags  =  nw  Iag[10];  //St  p  th  dbl-br  and  rsz  r  applt  

try  {  SrIag  =  ratIag(axWdth,axHght);  SrGC  =  

SrIaggtGraphs();  SrGCstClr(ClrlghtGray);  

SrGCllRt(0,0,axWdth,axHght);  

rsz(axWdth,axHght);  }ath  (Exptn  )  

{  prntStaTra();  }  

//lad  th  anatn  ags  nt  an  array  r  (nt  =0;<10;++)  {  Strng  

agFl  =  nw  Strng  (\"ags/D/T\"  +StrngvalO(+1)  +\"g\");  

ags[]  =  gtIag(gtDntBas(),agFl):  //Rgstr  ths  

ag  wth  th  trar  traraddIag(ags[],);  }  try  {  //Us  

trar  t  a  sr  all  th  ags  ar  ladd  trarwatFrAll();  }  

ath  (IntrrptdExptn  )  {}  ladd  =  tr;  }  

//Pant  th  rrnt  ra  pbl  vd  pant  (Graphs  g)  {    (ladd)  

{  gdrawIag(SrIag,0,0,ths);  }  }  

//Start  ,stp  r  rst  ag  pbl  vd  start()  {    (trarhID  

(ndx))  {  SrGCdrawIag  (ags[ndx],0,0,ths);  }  anatr  =  nw  

Thrad(ths);  anatrstart();  }  

//Rn,d  th  anatn  wr  hr  //Grab  an  ag,  pas  ,grab  th  nxt  

pbl  vd  rn()  {  //Gt  th  d    th  rrnt  thrad  Thrad    =  

ThradrrntThrad();  

//I  r  anatr  thrad  xst,and  s  th  rrnt  thrad  whl  

((anatr!=  nll)  &&  (anatr==))  {    (  trarhID  (ndx))  

{  //Clar  th  bagrnd  and  gt  th  nxt  ag  

SrGCllRt(0,0,100,100);  

SrGCdrawIag(ags[ndx],0,0,ths);  ndx++;  //Lp  ba  t  th  

bgnnng  and  p  gng    (ndx>=  agslngth)  {  ndx  =  0;  }  }  

//Dlay  hr  s  anatn  ls  nral  try  {  anatrslp(200);  }ath  

(IntrrptdExptn  )  {}  //Draw  th  nxt  ra  rpant();  }  }  }  

73  多  线  程  间  的  通  讯

731  生  产  者  和  消  费  者  

多  线  程  的  一  个  重  要  特  点  是  它  们  rg;  间  可  以  互  相  通  讯。  你  可  以  设  计  线  程  使  用  公  用  对  象,  每  个  线  程  都  可  以  独  立  操  作  公  用  对  象。  典  型  的  线  程  间  通  讯  建  立  在  生  产  者  和  消  费  者  模  型  上:  一  个  线  程  产  生  输  出;  另  一  个  线  程  使  用  输  入br  

让  我  们  创  建  一  个  简  单  的\"Alphabt  Sp\"生  产  者  和  相  应  的  消  费  者  

732  生  产  者  

生  产  者  将  从thrad类  里  派  生:  lass  Prdr  xtnds  Thrad  

{  prvat  Sp  sp;  prvat  Strng  alphabt  =  \"  

ABCDEFGHIJKLMNOPQRSTUVWXYZ\";  

pbl  Prdr(Sp  s)  {  //Kp  r  wn  py    th  shard  bjt  sp  

=  s;  }  

pbl  vd  rn()  {  har  ;  //Thrw  10  lttrs  nt  th  sp  r  (nt  

=0;<10;++)  {    =  alphabtharAt((nt)(Mathrand()  26));  

spadd();  //prnt  a  rrd    sr  addtn  

Systtprntln(\"Addd\"+  +  \"t  th  sp\");  //wat  a  bt  br  w  

add  th  nxt  lttr  try  {  slp((nt)(Mathrand()  1000));  }  ath  

(IntrrptdExptn  )  {}  }  }  }  

注  意  我  们  创  建  了Sp类  的  一  个  实  例。  生  产  者  用spadd()函  数  来  建  立  字  符  池。  

733  消  费  者

让  我  们  看  看  消  费  者  的  程  序:  lass  Cnsr  xtnds  Thrad  {  prvat  Sp  sp;  

pbl  Cnsr  (Sp  s)  {  //p  r  wn  py    th  shard  bjt  sp  

=  s;  }  

pbl  vd  rn()  {  har  ;  //Eat  10  lttrs  r  th  alphabt  sp  r  

(nt  I=0  ;<10;++)  {  //grab  n  lttr    =  spat();  //Prnt  t  th  

lttr  that  w  rtrvd  Systtprntln(\"At  a  lttr:  \"  +);  //try  

{  slp((nt)(Mathradd()2000));  }  ath  (IntrrptdExptn  )  {}  }  }  }  

同  理,  象  生  产  者  一  样,  我  们  用spat()来  处  理  信  息。  那  么,Sp类  到  底  干  什  么  呢?  

734  监  视  

Sp类  执  行  监  视  两  个  线  程  rg;  间  传  输  信  息  的  功  能。  监  视  是  多  线  程  中  不  可  缺  少  的  一  部  分,  因  为  它  保  持  了  通  讯  的  流  py;。  让  我  们  看  看Spjava文  件:  lass  Sp  {  prvat  har  br[]  =  nw  har[6];  prvat  nt  nxt  =  0;  //Flags  t  p  tra    

r  br  stats  prvat  blan  sFll  =  als;  prvat  blan  sEpty  

=  tr;  pbl  syshrnzd  har  at()  {  //W  an\'t  at    thr  sn\'t  anythng  

n  th  br  由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hs  

whn  sEpty  trns  als  }ath  (IntrrptdExptn  )  {}  }  //drnt  

th  nt,sn  w\'r  gng  t  at  n  lttr  nxt--;  //Dd  w  at  th  

last  lttr    (nxt==  0)  {  sEpty  =  tr;  }  //W  nw  th  br  an\'t  

b  ll,bas  w  jst  at  sFll  =  als;  nty();  //rtrn  th  lttr  

t  th  thrad  that  s  atng  rtrn  (br[nxt]);  }  

//thd  t  add  lttrs  t  th  br  pbl  synhrnzd  vd  add(har  

)  {  //Wat  arnd  ntl  thr\'s  r  t  add  anthr  lttr  whl  (sFll  

==  tr  )  {  try{  由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷h  

(IntrrptdExptn  )  {}  }  //add  th  lttr  t  th  nxt  avalabl  spt  

br[nxt]=;  //Chang  th  nxt  avalabl  spt  nxt++;  //Ar  w  ll;  

  (nxt  ==6)  {  sFll  =tr;  }  sEpty  =als;  nty();  }  }  sp类  包  含  两  个  重  要  特  征:  数  据  成  员br[]是  私  有  的,  功  能  成  员add()和at()是  公  有  的。  

数  据  私  有  避  免  了  生  产  者  和  消  费  者  直  接  获  得  数  据。  直  接  访  问  数  据  可  能  造  成  错  误。  例  如,  如  果  消  费  者  企  图  从  空  缓  冲  区  里  取  出  数  据,  你  将  得  到  不  必  要  的  异  常,  否  则,  你  只  能  锁  住  进  程。  同  步  访  问  方  法  避  免  了  破  坏  一  个  共  享  对  象。  当  生  产  者  向sp里  加  入  一  个  字  母  时,  消  费  者  不  能  吃  字  符,  诸  如  此  类。  这  种  同  步  是  维  持  共  享  对  象  完  整  性  的  重  要  方  面。nty()函  数  将  唤  醒  每  一  个  等  待  线  程。  等  待  线  程  将  继  续  它  的  访  问。  

735  联  系  起  来  

现  在  我  们  有  一  个  生  产  者,  一  个  消  费  者  和  一  个  共  享  对  象,  怎  样  实  现  它  们  的  交  互  呢?  我  们  只  需  要  一  个  简  单  的  控  制  程  序  来  启  动  所  有  的  线  程  并  确  信  每  一  个  线  程  都  是  访  问  的  同  一  个  共  享  对  象。  下  面  是  控  制  程  序  的  代  码,SpTstjava:  

lass  SpTst  {  pbl  stat  vd  an(Strng  args[])  {  Sp  s  =  nw  

Sp();  Prdr  p1  =  nw  Prdr(s);  Cnsr  1  =  nw  Cnsr(s);  

p1start();  1start();  }  }  

736  监  视  生  产  者  

生  产  者/消  费  者  模  型  程  序  经  常  用  来  实  现  远  程  监  视  功  能,  它  让  消  费  者  看  到  生  产  者  同  用  户  的  交  互  或  同  系  统  其  它  部  分  的  交  互。  例  如,  在  网  络  中,  一  组  生  产  者  线  程  可  以  在  很  多  工  作  站  上  运  行。  生  产  者  可  以    印  文  档,  文  档    印  后,  一  个  标  志  将  保  存  下  来。  一  个(或  多  个py;  消  费  者  将  保  存  标  志  并  在  晚  上  报  告  白  天    印  活  动  的  情  况。  另  外,  还  有  例  子  在  一  个  工  作  站  是  分  出  几  个  独  立  的  窗  口。  一  个  窗  口  用  作  用  户  输  入(生  产  者)  另  一  个  窗  口  作  出  对  输  入  的  反  应(消  费  者)。  

74  线  程API列  表  

下  面  是  一  个  常  用  的  线  程  类  的  方  法  函  数  列  表:  类  函  数:  以  下  是Thrad的  静  态  函  数,  即  可  以  直  接  从Thrad类  调  用。  

rrntThrad  返  回  正  在  运  行  的Thrad对  象  yld  停  止  运  行  当  前  线  程,  让  系  统  运  行  下  一  个  线  程  slp(nt  n)  让  当  前  线  程  睡  眠n毫  秒  对  象  函  数:  以  下  函  数  必  须  用Thrad的  实  例  对  象  来  调  用。  

start  start函  数  告  诉java运  行  系  统  为  本  线  程  建  立  一  个  执  行  环  境,  然  后  调  用  本  线  程  的rn()函  数。  rn  是  运  行  本  线  程  的  将  要  执  行  的  代  码,  也  是Rnnabl接  口  的  唯  一  函  数。  当  一  个  线  程  初  始  化  后,  由start函  数  来  调  用  它,  一  py;rn函  数  返  回,  本  线  程  也  就  终  止  了。  stp  让  某  线  程  马  上  终  止,  系  统  将  删  除  本  线  程  的  执  行  环  境  sspnd  与stp函  数  不  同,sspnd将  线  程  暂  停  执  行,  但  系  统  不  破  坏  线  程  的  执  行  环  境,  你  可  以  用rs来  恢  复  本  线  程  的  执  行  rs  恢  复  被  挂  起  的  线  程  进  入  运  行  状  态  stPrrty(nt  p)  给  线  程  设  置  优  先  级  gtPrrty  返  回  线  程  的  优  先  级  stNa(Strng  na)  给  线  程  设  置  名  称  gtNa  取  线  程  的  名  称  

本  章  小  结:  

1多  线  程  是java语  言  的  重  要  特  点,java语  言  用Thrad类  封  装  了  线  程  的  所  有  操  作。  2线  程  的  接  口  名  为Rnnabl  3线  程  间  同  步  机  制  为synhrnzd关  键  词  4线  程  间  通  讯  靠wat与nty消  息  

第  八  章  Java的\"  异  常\"

\"  异  常\"  指  的  是  程  序  运  行  时  出  现  的  非  正  常  情  况。  在  用  传  统  的  语  言  编  程  时,  程  序  员  只  能  通  过  函  数  的  返  回  值  来  发  出  错  误  信  息。  这  易  于  导  致  很  多  错  误,  因  为  在  很  多  情  况  下  需  要  知  道  错  误  产  生  的  内  部  细  节。  通  常,  用  全  局  变  量rrn来  存  储\"  异  常\"  的  类  型。  这  容  易  导  致  误  用,  因  为  一  个rrn的  值  有  可  能  在  被  处  理  rg;  前  被  另  外  的  错  误  覆  盖  掉。  即  使  最  优  美  的C语  言  程  序,  为  了  处  理\"  异  常\"  情  况,  也  常  求  助  于gt语  句。  Java对\"  异  常\"  的  处  理  是  面  向  对  象  的。  一  个Java的Exptn是  一  个  描  述\"  异  常\"  情  况  的  对  象。  当  出  现\"  异  常\"  情  况  时,  一  个Exptn对  象  就  产  生  了,  并  放  到  产  生  这  个\"  异  常\"  的  成  员  函  数  里。  

81  基础  

Java的\"  异  常\"  处  理  是  通  过5个  关  键  词  来  实  现  的:try,  ath,  thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hrw();  //再  抛  出  这  个\"  异  常\"  }  nally  {  }  

82  \"异  常\"  的  类  型

在\"  异  常\"  类  层  次  的  最  上  层  有  一  个  单  独  的  类  叫  做Thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n,  它  是  程  序  运  行  时  自  动  地  对  某  py;  错  误  作  出  反  应  而  产  生  的。  

83  不  捕  捉\"  异  常\"  

\"  异  常\"  对  象  是Java在  运  行  时  对  某  py;\"  异  常\"  情  况  作  出  反  应  而  产  生  的。  例  如,  下  面  这  个  小  程  序  包  含  一  个  整  数  被0除  的\"  异  常\"。  

lass  Ex0  {  pbl  stat  vd  an(Strng  args[])  {  nt  d  =  0;  nt  a  =  42/d;  }  }  

当Java执  行  这  个  除  法  时,  由  于  分  母  是0,  就  会  构  造  一  个\"  异  常\"  对  象  来  使  程  序  停  下  来  并  处  理  这  个  错  误  情  况,  在  运  行  时\"  抛  出\"(thrwpy;  这  个\"  异  常\"。  说\"  抛  出\"  是  因  为  它  象  一  个  滚  烫  的  马  铃  薯,  你  必  须  把  它  抓  住  并  立  即  处  理。  程  序  流  将  会  在  除  号  操  作  符  处  被    断,  然  后  检  查  当  前  的  调  用  堆  栈  来  查  找\"  异  常\"。  一  个\"  异  常\"  处  理  器  是  用  来  立  即  处  理\"  异  常\"  情  况  的。  在  这  个  例  子  里,  我  们  没  有  编  一  个\"  异  常\"  处  理  器,  所  以  缺  省  的  处  理  器  就  发  挥  作  用  了。  缺  省  的  处  理  器    印Exptn的  字  符  rg;  值  和  发  生  \"  异  常\"  的  地  点。  

下  面  是  我  们  的  小  例  子  的  输  出。  

C:\\>java  Ex0  javalangarthtExptn:  /  by  zr  at  Ex0an(Ex0java:4)  

84  try与ath  

通  常  我  们  希  望  自  己  来  处  理\"  异  常\"  并  继  续  运  行。  可  以  用try来  指  定  一  块  预  防  所  有\"  异  常\"  的  的  程  序。  紧  跟  在try程  序  后  面,  应  包  含  一  个ath子  句  来  指  定  你  想  要  捕  捉  的\"  异  常\"  的  类  型。  例  如,  下  面  的  例  子  是  在  前  面  的  例  子  的  基础上  构  造  的,  但  它  包  含  一  个try程  序  块  和  一  个ath子  句。  lass  x1  {  pbl  stat  vd  an(strng  args[])  {  try  {  nt  d  =  0;  nt  a  =  42  /  d;  }  ath  (arthtxptn  )  {  systtprntln(\"dvsn  by  zr\");  }  }  }  

ath子  句  的  目  标  是  解  决\"  异  常\"  情  况,  把  变  量  设  到  合  理  的  状  态,  并  象  没  有  出  错  一  样  继  续  运  行。  如  果  一  个  子  程  序  不  处  理  某  个\"  异  常\",  则  返  到  上  一  级  处  理,  直  到  最  外  一  级。  

85  多  个ath子  句

在  某  情  况  下,  同  一  段  程  序  可  能  产  生  不  止  一  种\"  异  常\"  情  况。  你  可  以  放  置  多  个ath子  句,  其  中  每  一  种\"  异  常\"  类  型  都  将  被  检  查,  第  一  个  与  rg;  匹  配  的  就  会  被  执  行。  如  果  一  个  类  和  其  子  类  都  有  的  话,  应  把  子  类  放  在  前  面,  否  则  将  永  远  不  会  到  达  子  类。  下  面  是  一  个  有  两  个ath子  句  的  程  序  的  例  子。  

lass  MltCath  {  pbl  stat  vd  an(Strng  args[])  {  try  {  nt  a  

=  argslngth;  Systtprntln(\"a  =  \"  +  a);  nt  b  =  42/a;  nt  []  =  

{1};  [42]  =  99;  }  ath(ArthtExptn  )  {  Systtprntln(\"dv  

by  0:  \"  +  );  }  ath(ArrayIndxOtOBndsExptn  )  

{  systtprntln(\"array  ndx  b:  \"  +  );  }  }  }  

如  果  在  程  序  运  行  时  不  跟  参  数,  将  会  引  起  一  个0做  除  数  的\"  异  常\",  因  为a的  值  为0。  如  果  我  们  提  py;  一  个  命  令  行  参  数,  将  不  会  产  生  这  个\"  异  常\",  因  为a的  值  大  于0。  但  会  引  起  一  个  ArrayIndxOtOBndxptn的\"  异  常\",  因  为  整  型  数  组的  长  度  是1,  却  给[42]赋  值。  下  面  是  以  上  两  种  情  况  的  运  行  结  果。  

C:\\>java  MltCath  a  =  0  dv  by  0:  javalangarthtxptn:  /  by  

zr  C:\\>java  MtCath  1  a  =  1  array  ndx  b:  

javalangArrayIndxOtOBndsExptn:42  

86  try语  句  的  嵌  套  

你  可  以  在  一  个  成  员  函  数  调  用  的  外  面  写  一  个try语  句,  在  这  个  成  员  函  数  内  部,  写  另  一  个try语  句  保  护  其  他  代  码。  每  当  遇  到  一  个try语  句,\"  异  常\"  的  框  架  就  放  到  堆  栈  上  面,  直  到  所  有  的try语  句  都  完  成。  如  果  下  一  级  的try语  句  没  有  对  某  种\"  异  常\"  进  行  处  理,  堆  栈  就  会  展  开,  直  到  遇  到  有  处  理  这  种\"  异  常\"  的try语  句。  下  面  是  一  个try语  句  嵌  套  的  例  子。  

lass  MltNst  {  stat  vd  prdr()  {  try  {  nt  []  =  {  1  }:  [42]  

=  99;  }  ath(ArrayIndxOtOBndsxptn  )  

{  Systtprntln(\"array  ndx  b:  \"  +  );  }  }  pbl  stat  vd  

an(Strng  args[])  {  try  {  nt  a  =  argslngth;  systtprntln(\"a  

=  \"  +  a);  nt  b  =  42/a;  prdr();  }  ath(arthtExptn  )  

{  Systtprntln(\"dv  by  0:  \"  +  );  }  }  }  

成  员  函  数prdr里  有  自  己  的try/ath控  制,  所  以an不  用  去  处  理  ArrayIndxOtOBndsExptn。  

87  thrw语  句

thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hrw语  句  的  通  常  形  式。  

thrw  ThrwablInstan;  

程  序  会  在thrw语  句  后  立  即  终  止,  它  后  面  的  语  句  执  行  不  到,  然  后  在  包  含  它  的  所  有try块  中  从  里  向  外  寻  找  含  有  与  其  匹  配  的ath子  句  的try块。  下  面  是  一  个  含  有thrw语  句  的  例  子。  

lass  Thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷ry  {  dpr();  }  

ath(NllPntrExptn  )  {  systtprntln(\"raght:  \"  +  );  }  }  }  

88  thrws语  句  

thrws用  来  标  明  一  个  成  员  函  数  可  能  抛  出  的  各  种\"  异  常\"。  对  大  多  数Exptn子  类  来  说,Java  编  译  器  会  强  迫  你  声  明  在  一  个  成  员  函  数  中  抛  出  的\"  异  常\"  的  类  型。  如  果\"  异  常\"  的  类  型  是Errr或  RntExptn,  或  它  们  的  子  类,  这  个  规  则  不  起  作  用,  因  为  这  py;  在  程  序  的  正  常  部  分  中  是  不  期  待  出  现  的。  如  果  你  想  明  确  地  抛  出  一  个RntExptn,  你  必  须  用thrws语  句  来  声  明  它  的  类  型。  这  就  重  新  定  义  了  成  员  函  数  

的  定  义  语  法:  typ  thd-na(arg-lst)  thrws  xptn-lst  {  }  

下  面  是  一  段  程  序,  它  抛  出  了  一  个\"  异  常\",  但  既  没  有  捕  捉  它,  也  没  有  用thrws来  声  明。  这  在  编  译  时  将  不  会  通  过。  

lass  ThrwsD1  {  stat  vd  prdr(  )  [  Systtprntln(\"nsd  

prdr\");  thrw  nw  IllgalAssExptn(\"d\");  }  pbl  stat  

vd  an(Strng  args[])  {  prdr(  );  }  }  

为  了  让  这  个  例  子  编  译  过  去,  我  们  需  要  声  明  成  员  函  数prdr抛  出  了IllgalAssExptn,  并  且  在  调  用  它  的  成  员  函  数an里  捕  捉  它。  下  面  是  正  确  的  例  子:  

lass  ThrwsD  {  stat  vd  prdr(  )  thrws  IllgalAssExptn  

{  Systtprntln(\"nsd  prdr\");  thrw  nw  

IllgalAssExptn(\"d\");  }  pbl  stat  vd  an(Strng  args[])  

{  try  {  prdr(  );  }  ath  (IllgalAssExptn  )  

{  Systtprntln(\"aght  \"  +  );  }  }  }  

下  面  是  输  出  结  果:  

C:\\>java  ThrwsD  nsd  prdr  aght  

javalangIllgalAssExptn:  d  

89  nally  

当  一  个\"  异  常\"  被  抛  出  时,  程  序  的  执  行  就  不  再  是  线  性  的,  跳  过  某  py;  行,  甚  至  会  由  于  没  有  与  rg;  匹  配  的ath子  句  而  过  早  地  返  回。  有  时  确  保  一  段  代  码  不  管  发  生  什  么\"  异  常\"  都  被  执  行  到  是  必  要  的,  关  键  词nally就  是  用  来  标  识  这  样  一  段  代  码  的。  即  使  你  没  有ath子  句,nally程  序  块  也  会  在  执  行  try程  序  块  后  的  程  序  rg;  前  执  行。  每  个try语  句  都  需  要  至  少  一  个  与  rg;  相  配  的ath子  句  或nally子  句。  一  个  成  员  函  数  返  回  到  调  用  它  的  成  员  函  数,  或  者  通  过  一  个  没  捕  捉  到  的\"  异  常\",  或  者  通  过  一  个  明  确  的rtrn语  句,nally子  句  总  是  恰  好  在  成  员  函  数  返  回  前  执  行。  下  面  是  一  个  例  子,  它  有  几  个  成  员  函  数,  每  个  成  员  函  数  用  不  同  的  途  径  退  出,  但  执  行  了nally子  句。  

lass  FnallyD  {  stat  vd  prA(  )  {  try  

{  Systtprntln(\"nsd  prA\");  thrw  nw  

RntExptn(\"d\");  }  nally  {  Systtprntln(\"prA\'s  

nally\");  }  }  stat  vd  prB(  )  {  try  {  Systtprntln(\"nsd  

prB\");  rtrn;  }  nally  {  Systtprntln(\"prB\'s  nally\");  }  }  

pbl  stat  vd  an(Strng  args[])  {  try  {  prA(  );  }  ath  (Exptn  

);  prB(  );  }  }  

下  面  是  这  个  例  子  的  运  行  结  果:  

C:\\>java  FnallyD  nsd  prA  prA\'s  nally  nsd  prB  prB\'s  nally  

本  章  小  结  

1  \"  异  常\"  指  的  是  程  序  运  行  时  出  现  的  非  正  常  情  况。  2  在\"  异  常\"  类  层  次  的  最  上  层  的  类  叫Thrwabl,  它  有  两  个  直  接  的  子  类:Exptn和Errr。  3  Java的\"  异  常\"  处  理  通  过5个  关  键  词  来  实  现:try,ath,thrw,thrws和nally。

第  九  章  Java输  入  输  出  操  作

91  Java  输  入  输  出  流

所  有  的  程  序  语  言  都  提  py;  与  本  机  文  件  系  统  交  互  的  方  式;Java也  不  例  外。  我  们  将  看  看Java是  怎  样  处  理  标  准  文  件  输  入  输  出  的(包  括stdn,stt,stdrr)。  当  你  在  网  络  上  开  发  小  程  序  时,  你  必  须  注  意  直  接  文  件  输  入  输  出  是  不  安  全  因  素  的  关  键。  大  多  数  用  户  设  置  他  们  的  浏  览  器,  可  让  你  自  由  的  访  问  他  们  的  文  件  系  统,  但  有  py;  不  让  你  访  问。  当  然,  如  果  你  开  发  你  内  部  的  应  用  程  序,  你  也  许  需  要  直  接  访  问  文  件。  标  准  输  入  输  出  Unx的  用  户,  或  其  他  基  于  命  令  行  系  统  的  用  户(如DOS),  都  知  道  标  准  输  入  输  出  的  含  义。  标  准  输  入  文  件  是  键  盘,  标  准  输  出  文  件  是  你  的  终  端  屏  幕。  标  准  错  误  输  出  文  件  也  指  向  屏  幕,  如  果  有  必  要,  它  也  可  以  指  向  另  一  个  文  件  以  便  和  正  常  输  出  区  分。  

系  统  类  Java通  过  系  统  类  达  到  访  问  标  准  输  入  输  出  的  功  能。  上  面  提  到  的  三  个  文  件  在  这  个  系  统  类  中  实  现:  Stdn  Systn作  为InptStra类  的  一  个  实  例  来  实  现stdn,  你  可  以  使  用rad()和sp(lng  n)两  个  成  员  函  数。rad()让  你  从  输  入  中  读  一  个  字  节,sp(lng  n)让  你  在  输  入  中  跳  过n个  字  节。  

Stt  Systt作  为PrntStra来  实  现stdt,  你  可  以  使  用prnt()和prntln()两  个  成  员  函  数。  这  两  个  函  数  支  持Java的  任  意  基  本  类  型  作  为  参  数。  

Stdrr  Systrr同stdt一  样  实  现stdrr。  象Systt一  样,  你  可  以  访  问PrntStra  成  员  函  数。  

92  标  准  输  入  输  出  例  子  

这  里  有  一  个  例  子,  功  能  象Unx里  的at或typ:  prt  java  lass  yCat{  pbl  vd  an(Strng  args[])  thrws  IOExptn{  nt  b;  nt  nt  =  0;  whl  ((b  =  Systnrad())  !=  

-1){  nt++;  Systtprnt((har)b);  }  Systtprntln();  

//blan  ln  Systrrprntln(\"ntd\"+nt+\"ttal  byts\");  }  }  

93  普  通  输  入  输  出  类  

除  了  基  本  的  键  盘  输  入  和  屏  幕  输  出  外,  我  们  还  需  要  联  系  文  件  的  输  入  输  出。  我  们  将  学  习  下  面  几  个  类:  l  FlInptStra  l  DataInptStra  l  FlOtptStra  l  DataOtptStra  

作  为  参  考,  再  列  出  一  py;  特  定  应  用  的  类:  l  PpdInptStra  l  BrdInptStra  l  PshBaInptStra  l  StraTnzr  l  PpdOtptStra  l  BrdOtptStra  l  RandAssFl  

我  们  不  在  此  讨  论  这  py;  类,  但  你  可  以  在JAVA_HOME/sr/java/目  录  里  查  看  每  个  类  的  成  员  函  数  定  义。  

94  文  件  

在  我  们  进  行  文  件  操  作  时,  需  要  知  道  关  于  文  件  的  信  息。Fl类  提  py;  了  一  py;  成  员  函  数  来  操  纵  文  件  和  获  得  文  件  的  信  息。  

941  创  建  一  个  新  的  文  件  对  象  

你  可  用  下  面  三  个  方  法  来  创  建  一  个  新  文  件  对  象:  Fl  yFl;  yFl  =  n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷d\");  

这  三  种  方  法  取  决  于  你  访  问  文  件  的  方  式。  例  如,  如  果  你  在  应  用  程  序  里  只  用  一  个  文  件,  第  一  种  创  建  文  件  的  结  构  是  最  容  易  的。  但  如  果  你  在  同  一  目  录  里    开  数  个  文  件,  则  第  二  种  或  第  三  种  结  构  更  好。  

942  文  件  测  试  和  使  用  

一  但  你  创  建  了  一  个  文  件  对  象,  你  便  可  以  使  用  以  下  成  员  函  数  来  获  得  文  件  相  关  信  息:  文  件  名  l  Strng  gtNa()  l  Strng  gtPath()  l  Strng  gtAbsltPath()  l  Strng  gtParnt()  l  blan  rnaT(Fl  nwNa)  文  件  测  试  l  blan  xsts()  l  blan  anWrt()  l  blan  anRad()  l  blan  sFl()  l  blan  sDrtry()  l  blan  sAbslt()  一  般  文  件  信  息  l  lng  lastMdd()  l  lng  lngth()  目  录  用  法  l  blan  dr()  l  Strng[]  lst()  

943  文  件  信  息  获  取  例  子  程  序

这  里  是  一  个  独  立  的  显  示  文  件  的  基  本  信  息  的  程  序,  文  件  通  过  命  令  行  参  数  传  输:  

prt  java;  lass  lIn{  Fl  lTCh;  pbl  stat  vd  an(Strng  args[])  thrws  IOExptn{    (argslngth>0){  r  (nt  =0;
如果你在阅读得很入味的时候,又正好有事离开,那请进行以下操作.