??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲高清中文字幕,午夜男人视频在线观看,久久亚洲精华国产精华液http://www.aygfsteel.com/iNeo/category/5328.htmlzh-cnFri, 02 Mar 2007 06:42:35 GMTFri, 02 Mar 2007 06:42:35 GMT60杂谈架构和架构设计师http://www.aygfsteel.com/iNeo/articles/24584.html只牵q只?/dc:creator>只牵q只?/author>Mon, 19 Dec 2005 03:08:00 GMThttp://www.aygfsteel.com/iNeo/articles/24584.htmlhttp://www.aygfsteel.com/iNeo/comments/24584.htmlhttp://www.aygfsteel.com/iNeo/articles/24584.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/24584.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/24584.html    
    良好的系l架构应该体现出应用本n的结构要? 所谓各个ؓ自己, 架构为大? 只要各个局部符合规? 应该由架构负责在合适的时刻按照合适的方式把它们组装在一? 一个良好的架构? 应该很少出现l构性的if语句, 不需要应用代码自己通过动态判断来定义某个Ҏ(gu)的触发时? 架构是一U规? 当然也就是一U局? 架构的可退化性是非常重要? 否则一旦出现抽象泄? 需要超出原有架构设计做出编码补充的时? 往往无法代码自然的融入原有的框架结? 则整个框架出现大面积的失效情? 而有的时候更p糕的情冉|一些关键性的资源处在原有技术架构的U有控制之中, 我们Z克服架构限制不得不采用各Utrick来hack原有框架, 造成错误的篏加和传播, 而补丁的补丁是最隄护的.

    架构问题q不是一成不变的. 在一些情形下无关紧要的问题在另一U情形下可能会成为灾难性的架构问题. 例如在多层B/S架构? 如果现在要求为每一个表增加一个对应的历史? q对其进行查看和l护操作. Z最大限度的重用代码, q要求我们的多层l构中的每一层都能够参数? q样我们才能用同L(fng)代码处理不同的数据表. 如果我们的money很, 弟够多, 有够的人月怸? 那么我们完全可以把业务表和历史表分开处理, 但如果反?我们׃遇到一个典型的架构问题.

    架构师未必有自己的框? 因ؓ设计不等价于创? 架构师只要知道如何把pȝ中的各种元素按照可行的方式组装在一起就可以? 但是一个架构设计是非常依赖于我们所能采用的技术手D늚, 当现有各U可用的技术元素都无法满我们的需求的时? 某些架构师可能会选择创造一U技术元? 当然, 创造是艰难? 它所要求的甚x不同的技? Sun的Green目创造了java语言, 从而开启了一个伟大的时代, q绝对不会是大多数架构设计师的选择(有趣的是,Green目本np|?. EJB现在q有多少人在真正使用, x当年多少架构师在吹嘘q些东西. 他们对于技术的把握真的那么幼E吗? 架构设计q不是凭I出现的, 当时可选的东西是如此, 而spring和hibernateq些都不属于架构设计本n的内?它们是一U创?
    
    架构师未必是团队的领D? 实,他的工作cM于编? 负责执行的一般是导演. 事实?一个徏{设计师是极直接领g个工E队?架构师也未必比高U程序员要高? 他们负责的是不同的内? 至于产品?商标及商标的相关元素"?技术市场架?{也不属于架构师的工作范? 他不能去抢品经理的饭碗. 当然,在国内的现实情况? 很多所谓的架构师所做的最重要的工作可能是公关工作, 向客L(fng)出所谓的理念, 与实际开发是不搭嘎的.     
    
    理论上说, 架构师可以不是编E的? 也可以不军_一些具体数据结构的选择, 但他不能不了解各U技术抉择潜在的影响. q就如同一个徏{设计师可以不精通工E力?但是他不能愚蠢到藐视重力, 设计出倒三角式的大? 与徏{不同的? 在Y件中我们所面(f)的不是一U?凝固的艺?, 我们无法以完全静态的方式理解代码,而必d头脑中把它们q行h. 架构师应该写下一些实际的代码, 以检验各个接口的可配合性ƈ获得对于代码l构的直接感? 实际? 按照现在软g业的成熟? 一般我们无法实现徏{中建筑设计师与土木工程师的分工, 很多时候Y件架构师都需要直接面对实现的l节. 如果l内~Z非常强?zhn)的coder, 有编E能力的架构师亲自操刀实现关键性代码的时候也是很多的.

    架构师必Ll验, 但他所依赖的不能只是经? 只要一架构师的年U? ׃知道以他们在q个世界上的存在旉, q不以使得他们l历各种技术细? 架构设计更多的是依赖我们对于pȝl构原理的理? 而经验可以让我们规避那些原理失效的地?例如pȝUbug). 君子非异能也, 善假于物? 很多时?我们更应该从有经验的朋友或者技术支持那里搜集技术细? 以确保它们能够满x们在架构上的原理性需? Know Why而不仅仅是Know How是非帔R要的. 一个农民发明家也许可以得到某个巧妙的机械设? 但是没有pȝ的掌握工E力? 他们是无法去开发精密的导弹控制pȝ?当然, 软g开发还处在非常原始的阶D? 掌握一些设计原理和设计模式多半也不q是五十步笑百步而已, l验的地位是无可替代?

    架构师不是预a? 在多变的业务环境? 架构师的目标不应该是预测到所有的变化可能, q把它们表达到系l架构中. q个世界上不乏一些耗资数十?设计三四q?但最l每个谈到它的h都要说一句shit的品开发项? 架构设计所能做到的最好的E度是自然的标注出系l的l构边界,成功的delay各种技术抉?

    架构师不是超? 他所考虑的东西也许要q一? 所需要^衡的利益也许要多一? 但是单独一个h是无法对整个产品或者项目的成|负责? 如果ThoughtWorks的Martin Follower来处理国内的某些目, 我估计他会死得很隄.架构师也是h, 也会犯错?甚至是很低的错? 而每个h都会有一些独特的x. l历的多? 你就会回归到l极的认? 一切都只是云, 只有money才是道?

2005-12-18 17:35 作? canonical【评?3?/FONT>【阅?97?/P>

]]>
_֍:Rundll32.exe文g详解http://www.aygfsteel.com/iNeo/articles/24001.html只牵q只?/dc:creator>只牵q只?/author>Thu, 15 Dec 2005 04:04:00 GMThttp://www.aygfsteel.com/iNeo/articles/24001.htmlhttp://www.aygfsteel.com/iNeo/comments/24001.htmlhttp://www.aygfsteel.com/iNeo/articles/24001.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/24001.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/24001.htmlwinexec(Pchar('StrCommand'),sw_Show);
其中"StrCommand"代表以下命o之一(使用Windows中的q行不要加引?Q?
"rundll32 shell32,Control_RunDLL" - q行控制面板
"rundll32 shell32,OpenAs_RunDLL" - 打开"打开方式"H口
"rundll32 shell32,ShellAboutA Info-Box" - 打开"关于"H口
"rundll32 shell32,Control_RunDLL desk.cpl" - 打开"昄属?H口
"rundll32 user,cascadechildwindows" - 层叠全部H口
"rundll32 user,tilechildwindows" - 最化所有的子窗?
"rundll32 user,repaintscreen" - h桌面
"rundll32 shell,shellexecute Explorer" - 重新q行W(xu)indows Explorer
"rundll32 keyboard,disable" - 锁写键盘
"rundll32 mouse,disable" - 让鼠标失?
"rundll32 user,swapmousebutton" - 交换鼠标按钮
"rundll32 user,setcursorpos" - 讄鼠标位置?0,0)
"rundll32 user,wnetconnectdialog" - 打开"映射|络驱动?H口
"rundll32 user,wnetdisconnectdialog" - 打开"断开|络驱动?H口
"rundll32 user,disableoemlayer" - 昄BSODH口, (BSOD) = Blue Screen Of
Death, 卌?
"rundll32 diskcopy,DiskCopyRunDll" - 打开盘复制H口
"rundll32 rnaui.dll,RnaWizard" - q行"Internetq接向导",
如果加上参数"/1"则ؓsilent模式
"rundll32 shell32,SHFormatDrive" - 打开"格式化磁?A)"H口
"rundll32 shell32,SHExitWindowsEx -1" - 冷启动Windows Explorer
"rundll32 shell32,SHExitWindowsEx 1" - x
"rundll32 shell32,SHExitWindowsEx 0" - 退当前用户
"rundll32 shell32,SHExitWindowsEx 2" Windows9x 快速重?
"rundll32 krnl386.exe,exitkernel" - 退出Windows 9x(无确?
"rundll rnaui.dll,RnaDial "MyConnect" - q行"|络q接"对话?
"rundll32 msprint2.dll,RUNDLL_PrintTestPage" - 选择打印机和打印试?
"rundll32 user,setcaretblinktime" - 讄光标闪烁速度
"rundll32 user, setdoubleclicktime" - 试鼠标双击速度
"rundll32 sysdm.cpl,InstallDevice_Rundll" - 搜烦非PnP讑֤
 控制面板中的各项功能

 winexec('rundll32.exe shell32.dll, Control_RunDLL', 9);
 {辅助选项 属?键盘}
 winexec('rundll32.exe shell32.dll, Control_RunDLL access.cpl, 1', 9);
 {辅助选项 属?声音}
 winexec('rundll32.exe shell32.dll, Control_RunDLL access.cpl, 2', 9);
 {辅助选项 属?昄}
 winexec('rundll32.exe shell32.dll, Control_RunDLL access.cpl, 3', 9);
 {辅助选项 属?鼠标}
 winexec('rundll32.exe shell32.dll, Control_RunDLL access.cpl, 4', 9);
 {辅助选项 属?常规}
 winexec('rundll32.exe shell32.dll, Control_RunDLL access.cpl, 5', 9);
 {d/删除E序 属?安装/卸蝲}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Appwiz.cpl, 1', 9);
 {d/删除E序 属?Windows安装E序}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Appwiz.cpl, 2', 9);
 {d/删除E序 属?启动盘}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Appwiz.cpl, 3', 9);
 {昄 属?背景}
 winexec('rundll32.exe shell32.dll, Control_RunDLL desk.cpl, 0', 9); 
 {昄 属?屏幕保护E序}
 winexec('rundll32.exe shell32.dll, Control_RunDLL desk.cpl, 1', 9);
 {昄 属?外观}
 winexec('rundll32.exe shell32.dll, Control_RunDLL desk.cpl, 2', 9);
 {昄 属?讄}
 winexec('rundll32.exe shell32.dll, Control_RunDLL desk.cpl, 3', 9);
 {Internet 属?常规}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 0',
9);
 {Internet 属?安全}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 1',
9);
 {Internet 属?内容}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 2',
9);
 {Internet 属?q接}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 3',
9);
 {Internet 属?E序}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 4',
9);
 {Internet 属?高}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Inetcpl.cpl, 5',
9);
 {区域讄 属?区域讄}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Intl.cpl, 0', 9);
 {区域讄 属?数字}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Intl.cpl, 1', 9);
 {区域讄 属?货币}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Intl.cpl, 2', 9);
 {区域讄 属?旉}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Intl.cpl, 3', 9);
 {区域讄 属?日期}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Intl.cpl, 4', 9);
 
 winexec('rundll32.exe shell32.dll, Control_RunDLL Joy.cpl, 0', 9);


winexec('rundll32.exe shell32.dll, Control_RunDLL Joy.cpl, 1', 9);
 {鼠标 属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Main.cpl', 9);
 {多媒?属?音频}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Mmsys.cpl, 0', 9);
 {多媒?属?视频}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Mmsys.cpl, 1', 9);
 {多媒?属?MIDI}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Mmsys.cpl, 2', 9);
 {多媒?属?CD音乐}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Mmsys.cpl, 3', 9);
 {多媒?属?讑֤}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Mmsys.cpl, 4', 9);
 {调制解调?属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Modem.cpl', 9);
 
 winexec('rundll32.exe shell32.dll, Control_RunDLL Netcpl.cpl', 9);
 {密码 属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Password.cpl', 9);
 {扫描仪与数字相机 属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Sticpl.cpl', 9);
 {pȝ 属?常规}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Sysdm.cpl, 0', 9);
 {pȝ 属?讑֤理器}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Sysdm.cpl, 1', 9);
 {pȝ 属?g配置文g}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Sysdm.cpl, 2', 9);
 {pȝ 属?性能}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Sysdm.cpl, 3', 9);
 {日期/旉 属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL timedate.cpl', 9);
 {甉|理 属性}
 winexec('rundll32.exe shell32.dll, Control_RunDLL Powercfg.cpl', 9);
 
 winexec('rundll32.exe shell32.dll, Control_RunDLL Telephon.cpl', 9);
关于调用后的判断处理Q?
先声明一个cardinalcd的变量RtnCardinal获取q回D行判断如Q?
RtnCardinal := winexec('rundll32.exe shell32.dll, Control_RunDLL
Telephon.cpl', 9);
 q回?可能原因
 0 E序出内存 
ERROR_BAD_FORMAT E序Z个非法的Win32.EXEE序
ERROR_FILE_NOT_FOUND 指定文g没找到 
ERROR_PATH_NOT_FOUND 指定路径没找?

使用Ҏ(gu)Q?
点击“开始-E式QMsQDos方式”,q入Dos视窗Q然後键?rundll32.exe
user.exe,restartwindows"Q再按下回R键,q时你将看到Q机器被重启了!怎么P是不是很有趣Q?
  当然QRundll的功能绝不仅仅是重启你的机器。其实,Rundll者,֐思义Q执行Dll也,它的功能是以命令列的方式呼叫Windows的动态链l库QRundll32.exe与Rundll.exe的区别就在於前者是呼叫32位的铄库,而後者是q用?6位的铄库,它们的命令格式是Q?
  RUNDLL.EXE Q,
  q里要注意三点:1.Dll案名中不能含有I格Q比如该案位於c:Program
Files目录Q你要把q个路径Ҏ(gu)c:Progra?Q?.Dll档案名与Dll入口炚w的逗号不能,否则E式出错ƈ且不会给ZQ何资讯!3.q是最重要的一点:Rundll不能用来呼叫含返回值参数的DllQ例如Win32API中的GetUserName(),GetTextFace(){。在Visual
Basic中,提供了一条执行外部程式的指oShell,格式为:
  Shell “命令列?
  如果能配合Rundll32.exe用好Shell指oQ会使?zhn)的VBE式拥有用其他方法难以甚x法实现的效果Q仍以重启ؓ例,传统的方法需要你在VB工程中先建立一个模l,然後写入WinAPI的声明,最後才能在E式中呼叫。而现在只需一?
  Shell “rundll32.exe
user.exe,restartwindows”就搞定了!是不是方便多了?
  实际上,Rundll32.exe在呼叫各UWindows控制面板和系l选项斚w有著独特的优ѝ下面,我就本人在因特|上攉的有关Rundll的指令列丑֦下(很有用的Q能省去你很多呼叫Windows
API的时_Q)Q供大家在程式设计中引用Q?
  命o? rundll32.exe shell32.dll,Control_RunDLL
  功能: 昄控制面板
  命o? rundll32.exe shell32.dll,Control_RunDLL access.cpl,,1
  功能: 昄“控刉板-辅助选项Q键盘”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL access.cpl,,2
  功能: 昄“控刉板-辅助选项Q声音”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL access.cpl,,3
  功能: 昄“控刉板-辅助选项Q显C”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL access.cpl,,4
  功能: 昄“控刉板-辅助选项Q滑鼠”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL access.cpl,,5
  功能: 昄“控刉板-辅助选项Q传l”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl @1
  功能: 执行“控刉板-d新硬体”向对{?
  命o? rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL AddPrinter
  功能: 执行“控刉板-d新印表机”向对{?
  命o? rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,1
  功能: 昄 “控刉板-d/删除E式Q安?卸蝲?面板?
  命o? rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,2
  功能: 昄 “控刉板-d/删除E式Q安装Windows?面板?
  命o? rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,3
  功能: 昄 “控刉板-d/删除E式Q启动盘?面板?
  命o? rundll32.exe syncui.dll,Briefcase_Create
  功能: 在桌面上建立一个新的“我的公文包”?
  命o? rundll32.exe diskcopy.dll,DiskCopyRunDll
  功能: 昄复制软碟视窗
  命o? rundll32.exe apwiz.cpl,NewLinkHere Q?
  功能:
昄“徏立快h式”的对话框,所建立的快h式的位置由%1参数军_?
  命o? rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,0
  功能: 昄“日期与旉”选项视窗?


命o? rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,1
  功能: 昄“时区”选项视窗?
  命o? rundll32.exe rnaui.dll,RnaDial [某个拨号q接的名U]
  功能:
昄某个拨号q接的拨可H。如果已l拨可接,则显C目前的q接状态的视窗?
  命o? rundll32.exe rnaui.dll,RnaWizard
  功能: 昄“新建拨可接”向导的视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0
  功能: 昄“显C属性-背景”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1
  功能: 昄“显C属性-萤屏保护”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2
  功能: 昄“显C属性-外观”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3
  功能: 昄昄“显C属性-属性”选项视窗?
  命o? rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL FontsFolder
  功能: 昄Windows的“字体”案夹?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @3
  功能: 同样是显CWindows的“字体”案夹?
  命o? rundll32.exe shell32.dll,SHformatDrive
  功能: 昄格式化Y对话框?
  命o? rundll32.exe shell32.dll,Control_RunDLL joy.cpl,,0
  功能: 昄“控刉板-游戏控制器-一般”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL joy.cpl,,1
  功能: 昄“控刉板-游戏控制器-q阶”选项视窗?
  命o? rundll32.exe mshtml.dll,PrintHTML (HTML文档)
  功能: 列印HTML文?
  命o? rundll32.exe shell32.dll,Control_RunDLL mlcfg32.cpl
  功能: 昄Microsoft Exchange一般选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @0
  功能: 昄“控刉板-滑鼠?选项 ?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @1
  功能: 昄 “控刉板-键盘属性-速度”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @1,,1
  功能: 昄 “控刉板-键盘属性-语言”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @2
  功能: 昄Windows“印表机”档案夹?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @3
  功能: 昄Windows“字体”案夹?
  命o? rundll32.exe shell32.dll,Control_RunDLL main.cpl @4
  功能: 昄“控刉板-输入法属性-输入法”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL modem.cpl,,add
  功能: 执行“添加新调制解调器”向对{?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,0
  功能: 昄“控刉板-多媒体属性-音频”属性页?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,1
  功能: 昄“控刉板-多媒体属性-视频”属性页?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,2
  功能: 昄“控刉板-多媒体属性-MIDI”属性页?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,3
  功能: 昄“控刉板-多媒体属性-CD音乐”属性页?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,4
  功能: 昄“控刉板-多媒体属性-讑֤”属性页?
  命o? rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl @1
  功能: 昄“控刉板-声音”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL netcpl.cpl
  功能: 昄“控刉板-|\”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL odbccp32.cpl
  功能: 昄ODBC32资料理选项视窗?
  命o? rundll32.exe shell32.dll,OpenAs_RunDLL
功能: 昄指定案(drive:pathfilename)的“打开方式”对话框?
  命o? rundll32.exe shell32.dll,Control_RunDLL password.cpl
  功能: 昄“控刉板-密码”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL powercfg.cpl
  功能: 昄“控刉板-甉|理属性”选项视窗?
  命o? rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL
PrintersFolder
  功能: 昄Windows“印表机”案夹?同rundll32.exe
shell32.dll,Control_RunDLL main.cpl @2)
  命o? rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,0
  功能: 昄“控刉板-区域讄属性-区域讄”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,1
  功能: 昄“控刉板-区域讄属性-数字”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,2
  功能: 昄“控刉板-区域讄属性-货币”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,3
  功能: 昄“控刉板-区域讄属性-旉”选项视窗?
  命o? rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4
  功能: 昄“控刉板-区域讄属性-日期”选项视窗?
  命o? rundll32.exe desk.cpl,InstallScreenSaver [萤屏保护档案名]
  功能:
指定的萤屏保护案讄为Windows的屏保,q显C屏保护属性视H?
  命o? rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,0
  功能: 昄“控刉板-pȝ属性-传统”属性视H?
  命o? rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,1
  功能: 昄“控刉板-pȝ属性-讑֤理器”属性视H?
  命o? rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,2
  功能: 昄“控刉板-pȝ属性-体配置案”属性视H?
  命o? rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,3
  功能: 昄“控刉板-pȝ属性-性能”属性视H?
  命o? rundll32.exe user.exe,restartwindows
  功能: 关闭所有程式ƈ重启机器?
  命o? rundll32.exe user.exe,exitwindows
  功能: 关闭所有程式ƈx?
  命o? rundll32.exe shell32.dll,Control_RunDLL telephon.cpl
  功能: 昄“拨号属性”选项视窗
  命o? rundll32.exe shell32.dll,Control_RunDLL themes.cpl
  功能: 昄“桌面主旨”选项面板
  当然Q不止是VisualBasicQ象Delphi.VisualCQ+{其他程式设计语a也可以通过呼叫外部命o的方法来使用Rundll的这些功能,具体Ҏ(gu)q里׃再详l叙qC。灵zȝ使用Rundll,一定会使你的程式设计轻L松,辑ֈ事半功倍的效果



]]>
java多线E设计模?/title><link>http://www.aygfsteel.com/iNeo/articles/23754.html</link><dc:creator>只牵q只?/dc:creator><author>只牵q只?/author><pubDate>Wed, 14 Dec 2005 00:54:00 GMT</pubDate><guid>http://www.aygfsteel.com/iNeo/articles/23754.html</guid><wfw:comment>http://www.aygfsteel.com/iNeo/comments/23754.html</wfw:comment><comments>http://www.aygfsteel.com/iNeo/articles/23754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/iNeo/comments/commentRss/23754.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/iNeo/services/trackbacks/23754.html</trackback:ping><description><![CDATA[<H2>java多线E设计模?</H2> <P>java语言已经内置了多U程支持Q所有实现Runnable接口的类都可被启动一个新U程Q新U程会执行该实例的run()Ҏ(gu)Q当run()Ҏ(gu)执行完毕后,U程q束了。一旦一个线E执行完毕,q个实例׃能再重新启动Q只能重新生成一个新实例Q再启动一个新U程?/P> <P>ThreadcL实现了Runnable接口的一个实例,它代表一个线E的实例Qƈ且,启动U程的唯一Ҏ(gu)是通过Threadcȝstart()实例Ҏ(gu)Q?/P> <P>Thread t = new Thread();<BR>t.start();</P> <P>start()Ҏ(gu)是一个nativeҎ(gu)Q它?yu)启动一个新U程Qƈ执行run()Ҏ(gu)。Threadc默认的run()Ҏ(gu)什么也不做退Z。注意:直接调用run()Ҏ(gu)q不会启动一个新U程Q它和调用一个普通的javaҎ(gu)没有什么区别?/P> <P>因此Q有两个Ҏ(gu)可以实现自己的线E:</P> <P>Ҏ(gu)1Q自qcextend ThreadQƈ复写run()Ҏ(gu)Q就可以启动新线Eƈ执行自己定义的run()Ҏ(gu)。例如:</P> <P>public class MyThread extends Thread {<BR>    public run() {<BR>        System.out.println("MyThread.run()");<BR>    }<BR>}</P> <P>在合适的地方启动U程Qnew MyThread().start();</P> <P>Ҏ(gu)2Q如果自qcdlextends另一个类Q就无法直接extends ThreadQ此Ӟ必须实现一个Runnable接口Q?/P> <P>public class MyThread extends OtherClass implements Runnable {<BR>    public run() {<BR>        System.out.println("MyThread.run()");<BR>    }<BR>}</P> <P>Z启动MyThreadQ需要首先实例化一个ThreadQƈ传入自己的MyThread实例Q?/P> <P>MyThread myt = new MyThread();<BR>Thread t = new Thread(myt);<BR>t.start();</P> <P>事实上,当传入一个Runnable target参数lThread后,Thread的run()Ҏ(gu)׃调用target.run()Q参考JDK源代码:</P> <P>public void run() {<BR>    if (target != null) {<BR>        target.run();<BR>    }<BR>}</P> <P>U程q有一些Name, ThreadGroup, isDaemon{设|,׃和线E设计模式关联很,q里׃多说了?BR></P> <P>׃同一q程内的多个U程׃n内存I间Q在Java中,是׃n实例Q当多个U程试图同时修改某个实例的内Ҏ(gu)Q就会造成冲突Q因此,U程必须实现׃n互斥Q多线E同步?/P> <P>最单的同步是将一个方法标CؓsynchronizedQ对同一个实例来_M时刻只能有一个synchronizedҎ(gu)在执行。当一个方法正在执行某个synchronizedҎ(gu)Ӟ其他U程如果惌执行q个实例的Q意一个synchronizedҎ(gu)Q都必须{待当前执行 synchronizedҎ(gu)的线E退出此Ҏ(gu)后,才能依次执行?/P> <P>但是Q非synchronizedҎ(gu)不受影响Q不当前有没有执行synchronizedҎ(gu)Q非synchronizedҎ(gu)都可以被多个U程同时执行?/P> <P>此外Q必L意,只有同一实例的synchronizedҎ(gu)同一旉只能被一个线E执行,不同实例的synchronizedҎ(gu)是可以ƈ发的。例如,class A定义了synchronizedҎ(gu)sync()Q则不同实例a1.sync()和a2.sync()可以同时׃个线E来执行?BR></P> <P>多线E同步的实现最l依赖锁机制。我们可以想象某一׃n资源是一间屋子,每个人都是一个线E。当A希望q入戉KӞ他必获得门锁,一旦A获得门锁Q他q去后就立刻门锁上Q于是B,C,D...׃得不在门外等待,直到A释放锁出来后QB,C,D...中的某一人抢C该锁Q具体抢法依赖于 JVM的实玎ͼ可以先到先得Q也可以随机挑选)Q然后进屋又门锁上。这PM时刻最多有一人在屋内Q用共享资源)?/P> <P>Java语言规范内置了对多线E的支持。对于JavaE序来说Q每一个对象实例都有一把“锁”,一旦某个线E获得了该锁Q别的线E如果希望获得该锁,只能{待q个U程释放锁之后。获得锁的方法只有一个,是synchronized关键字。例如:</P> <P>public class SharedResource {<BR>    private int count = 0;<BR><BR>    public int getCount() { return count; }<BR><BR>    public <FONT color=#ff0000><STRONG>synchronized</STRONG></FONT> void setCount(int count) { this.count = count; }<BR><BR>}</P> <P>同步Ҏ(gu)public synchronized void setCount(int count) { this.count = count; } 事实上相当于Q?/P> <P>public void setCount(int count) {<BR>    <STRONG><FONT color=#339966>synchronized(this) { // 在此获得this?BR></FONT><FONT color=#ff0000>         this.count = count;</FONT></STRONG><BR>    <FONT color=#339966><STRONG>} // 在此释放this?BR></STRONG></FONT>}</P> <P>U色部分表示需要同步的代码D,该区域ؓ“危险区域”,如果两个以上的线E同时执行,会引发冲H,因此Q要更改SharedResource的内部状态,必须先获得SharedResource实例的锁?/P> <P>退出synchronized块时Q线E拥有的锁自动释放,于是Q别的线E又可以获取该锁了?/P> <P>Z提高性能Q不一定要锁定thisQ例如,SharedResource有两个独立变化的变量Q?/P> <P>public class SharedResouce {<BR>    private int a = 0;<BR>    private int b = 0;<BR><BR>    public synchronized void setA(int a) { this.a = a; }<BR><BR>    public synchronized void setB(int b) { this.b = b; }<BR>}</P> <P>若同步整个方法,则setA()的时候无法setB()QsetB()时无法setA()。ؓ了提高性能Q可以用不同对象的锁:</P> <P>public class SharedResouce {<BR>    private int a = 0;<BR>    private int b = 0;<BR>    private Object sync_a = new Object();<BR>    private Object sync_b = new Object();<BR><BR>    public void setA(int a) {<BR>        <FONT color=#339966><STRONG>synchronized(sync_a) {<BR></STRONG></FONT>            this.a = a;<BR>        }<BR>    }<BR><BR>    public synchronized void setB(int b) {<BR>        <FONT color=#339966><STRONG>synchronized(sync_b) {<BR></STRONG></FONT>            this.b = b;<BR>        }<BR>    }<BR>}<BR></P> <P>通常Q多U程之间需要协调工作。例如,览器的一个显C图片的U程displayThread惌执行昄囄的Q务,必须{待下蝲U程 downloadThread该囄下蝲完毕。如果图片还没有下蝲完,displayThread可以暂停Q当downloadThread完成了Q务后Q再通知displayThread“图片准备完毕,可以昄了”,q时QdisplayThreadl箋执行?/P> <P>以上逻辑单的说就是:如果条g不满I则等待。当条g满Ӟ{待该条件的U程被唤醒。在Java中,q个机制的实C赖于wait/notify。等待机制与锁机制是密切兌的。例如:</P> <P>synchronized(obj) {<BR>    while(!condition) {<BR>        obj.<STRONG><FONT color=#0000ff>wait()</FONT></STRONG>;<BR>    }<BR>    obj.doSomething();<BR>}</P> <P>当线EA获得了obj锁后Q发现条件condition不满I无法l箋下一处理Q于是线EAwait()?/P> <P>在另一U程B中,如果B更改了某些条Ӟ使得U程A的condition条g满了,可以唤醒线EAQ?/P> <P>synchronized(obj) {<BR>    condition = true;<BR>    obj.notify();<BR>}</P> <P><STRONG><FONT color=#ff0000>需要注意的概念是:</FONT></STRONG></P> <P># 调用obj的wait(), notify()Ҏ(gu)前,必须获得obj锁,也就是必d在synchronized(obj) {...} 代码D内?/P> <P># 调用obj.wait()后,U程A释放了obj的锁Q否则线EB无法获得obj锁,也就无法在synchronized(obj) {...} 代码D内唤醒A?/P> <P># 当obj.wait()Ҏ(gu)q回后,U程A需要再ơ获得obj锁,才能l箋执行?/P> <P># 如果A1,A2,A3都在obj.wait()Q则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM军_Q?/P> <P># obj.notifyAll()则能全部唤醒A1,A2,A3Q但是要l箋执行obj.wait()的下一条语句,必须获得obj锁,因此QA1,A2,A3只有一个有Z获得锁l执行,例如A1Q其余的需要等待A1释放obj锁之后才能l执行?/P> <P># 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此QA1,A2,A3虽被唤醒Q但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后QA1,A2,A3中的一个才有机会获得锁l箋执行?/P><BR> <P>前面讲了wait/notify机制QThreadq有一个sleep()静态方法,它也能ɾU程暂停一D|间。sleep与wait的不同点是: sleepq不释放锁,q且sleep的暂停和wait暂停是不一L(fng)。obj.wait会ɾU程q入obj对象的等待集合中q等待唤醒?/P> <P>但是wait()和sleep()都可以通过interrupt()Ҏ(gu)打断U程的暂停状态,从而ɾU程立刻抛出InterruptedException?/P> <P>如果U程A希望立即l束U程BQ则可以对线EB对应的Thread实例调用interruptҎ(gu)。如果此ȝEB正在 wait/sleep/joinQ则U程B会立L出InterruptedExceptionQ在catch() {} 中直接return卛_安全地结束线E?/P> <P>需要注意的是,InterruptedException是线E自׃内部抛出的,q不是interrupt()Ҏ(gu)抛出的。对某一U程调用 interrupt()Ӟ如果该线E正在执行普通的代码Q那么该U程Ҏ(gu)׃会抛出InterruptedException。但是,一旦该U程q入?wait()/sleep()/join()后,׃立刻抛出InterruptedException?/P><BR> <P>GuardedSuspention模式主要思想是:</P> <P>当条件不满ӞU程{待Q直到条件满xQ等待该条g的线E被唤醒?/P> <P>我们设计一个客L(fng)U程和一个服务器U程Q客L(fng)U程不断发送请求给服务器线E,服务器线E不断处理请求。当h队列为空Ӟ服务器线E就必须{待Q直到客L(fng)发送了h?/P> <P>先定义一个请求队列:Queue</P> <P>package com.crackj2ee.thread;<BR><BR>import java.util.*;<BR><BR>public class Queue {<BR>    private List queue = new LinkedList();<BR><BR>    public synchronized Request <FONT color=#ff0000>getRequest</FONT>() {<BR>        <FONT color=#0000ff><STRONG>while(queue.size()==0) {<BR></STRONG></FONT>            try {<BR>                this.wait();<BR>            }<BR>            catch(InterruptedException ie) {<BR>                return null;<BR>            }<BR>        }<BR>        return (Request)queue.remove(0);<BR>    }<BR><BR>    public synchronized void <FONT color=#ff0000>putRequest</FONT>(Request request) {<BR>        queue.add(request);<BR>        <FONT color=#993300><STRONG>this.notifyAll();</STRONG></FONT><BR>    }<BR><BR>}</P> <P>蓝色部分是服务器线E的{待条gQ而客L(fng)U程在放入了一个request后,׃服务器线E等待条件满I于是唤醒服务器线E?/P> <P>客户端线E:ClientThread</P> <P>package com.crackj2ee.thread;<BR><BR>public class ClientThread extends Thread {<BR>    private Queue queue;<BR>    private String clientName;<BR><BR>    public ClientThread(Queue queue, String clientName) {<BR>        this.queue = queue;<BR>        this.clientName = clientName;<BR>    }<BR><BR>    public String toString() {<BR>        return "[ClientThread-" + clientName + "]";<BR>    }<BR><BR>    public void run() {<BR>        for(int i=0; i<100; i++) {<BR>            Request request = new Request("" + (long)(Math.random()*10000));<BR>            System.out.println(this + " send request: " + request);<BR>            <STRONG><FONT color=#ff0000>queue.putRequest(request);<BR></FONT></STRONG>            try {<BR>                Thread.sleep((long)(Math.random() * 10000 + 1000));<BR>            }<BR>            catch(InterruptedException ie) {<BR>            }<BR>        }<BR>        System.out.println(this + " shutdown.");<BR>    }<BR>}</P> <P>服务器线E:ServerThread</P> <P>package com.crackj2ee.thread;<BR>public class ServerThread extends Thread {<BR>    private boolean stop = false;<BR>    private Queue queue;<BR><BR>    public ServerThread(Queue queue) {<BR>        this.queue = queue;<BR>    }<BR><BR>    public void shutdown() {<BR>        stop = true;<BR>        this.interrupt();<BR>        try {<BR>            this.join();<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR><BR>    public void run() {<BR>        while(!stop) {<BR>            <FONT color=#ff0000><STRONG>Request request = queue.getRequest();<BR></STRONG></FONT>            System.out.println("[ServerThread] handle request: " + request);<BR>            try {<BR>                Thread.sleep(2000);<BR>            }<BR>            catch(InterruptedException ie) {}<BR>        }<BR>        System.out.println("[ServerThread] shutdown.");<BR>    }<BR>}</P> <P>服务器线E在U色部分可能会阻塞,也就是说QQueue.getRequest是一个阻塞方法。这和java标准库的许多IOҎ(gu)cM?/P> <P>最后,写一个Main来启动他们:</P> <P>package com.crackj2ee.thread;<BR><BR>public class Main {<BR><BR>    public static void main(String[] args) {<BR>        Queue queue = new Queue();<BR>        ServerThread server = new ServerThread(queue);<BR>        <FONT color=#ff0000><STRONG>server.start();<BR></STRONG></FONT>        ClientThread[] clients = new ClientThread[5];<BR>        for(int i=0; i<clients.length; i++) {<BR>            clients[i] = new ClientThread(queue, ""+i);<BR>            <FONT color=#ff0000><STRONG>clients[i].start();<BR></STRONG></FONT>        }<BR>        try {<BR>            Thread.sleep(100000);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>        server.shutdown();<BR>    }<BR>}</P> <P>我们启动?个客L(fng)U程和一个服务器U程Q运行结果如下:</P> <P>[ClientThread-0] send request: Request-4984<BR>[ServerThread] handle request: Request-4984<BR>[ClientThread-1] send request: Request-2020<BR>[ClientThread-2] send request: Request-8980<BR>[ClientThread-3] send request: Request-5044<BR>[ClientThread-4] send request: Request-548<BR>[ClientThread-4] send request: Request-6832<BR>[ServerThread] handle request: Request-2020<BR>[ServerThread] handle request: Request-8980<BR>[ServerThread] handle request: Request-5044<BR>[ServerThread] handle request: Request-548<BR>[ClientThread-4] send request: Request-1681<BR>[ClientThread-0] send request: Request-7859<BR>[ClientThread-3] send request: Request-3926<BR>[ServerThread] handle request: Request-6832<BR>[ClientThread-2] send request: Request-9906<BR>......</P> <P>可以观察到ServerThread处理来自不同客户端的h?/P> <P><STRONG><FONT color=#ff0000>思?/FONT></STRONG></P> <P>Q: 服务器线E的wait条gwhile(queue.size()==0)能否换成if(queue.size()==0)?</P> <P>A: 在这个例子中可以Q因为服务器U程只有一个。但是,如果服务器线E有多个Q例如Web应用E序有多个线E处理ƈ发请求,q非常普遍)Q就会造成严重问题?/P> <P>Q: 能否用sleep(1000)代替wait()?</P> <P>A: l对不可以。sleep()不会释放锁,因此sleep期间别的U程Ҏ(gu)没有办法调用getRequest()和putRequest()Q导致所有相关线E都被阻塞?/P> <P>Q: (Request)queue.remove(0)可以攑ֈsynchronized() {}块外面吗Q?/P> <P>A: 不可以。因为while()是测试queueQremove()是用queueQ两者是一个原子操作,不能攑֜synchronized外面?/P> <P><STRONG><FONT color=#ff0000>ȝ</FONT></STRONG></P> <P>多线E设计看似简单,实际上必非总l地考虑各种锁定/同步的条ӞE不心Q就可能出错。ƈ且,当线E较?yu)时Q很可能发现不了问题Q一旦问题出现又难以调试?/P> <P>所q的是,已有一些被验证q的模式可以供我们用,我们会l介l一些常用的多线E设计模式?BR></P> <P>前面谈了多线E应用程序能极大地改善用L(fng)应。例如对于一个Web应用E序Q每当一个用戯求服务器q接Ӟ服务器就可以启动一个新U程为用h务?/P> <P>然而,创徏和销毁线E本w就有一定的开销Q如果频J创建和销毁线E,CPU和内存开销׃可忽略,垃圾攉器还必须负担更多的工作。因此,U程池就是ؓ了避免频J创建和销毁线E?/P> <P>每当服务器接受了一个新的请求后Q服务器׃U程池中挑选一个等待的U程q执行请求处理。处理完毕后Q线Eƈ不结束,而是转ؓd状态再ơ被攑օU程池中。这样就避免了频J创建和销毁线E?/P> <P>Worker Pattern实现了类似线E池的功能。首先定义Task接口Q?/P> <P>package com.crackj2ee.thread;<BR>public interface Task {<BR>    void <STRONG><FONT color=#0000ff>execute</FONT></STRONG>();<BR>}</P> <P>U程负责执行execute()Ҏ(gu)。注意到d是由子类通过实现execute()Ҏ(gu)实现的,U程本nq不知道自己执行的Q务。它只负责运行一个耗时的execute()Ҏ(gu)?/P> <P>具体d由子cd玎ͼ我们定义了一个CalculateTask和一个TimerTaskQ?/P> <P>// CalculateTask.java<BR>package com.crackj2ee.thread;<BR>public class CalculateTask implements Task {<BR>    private static int count = 0;<BR>    private int num = count;<BR>    public CalculateTask() {<BR>        count++;<BR>    }<BR>    public void <FONT color=#0000ff><STRONG>execute</STRONG></FONT>() {<BR>        System.out.println("[CalculateTask " + num + "] start...");<BR>        try {<BR>            Thread.sleep(3000);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>        System.out.println("[CalculateTask " + num + "] done.");<BR>    }<BR>}</P> <P>// TimerTask.java<BR>package com.crackj2ee.thread;<BR>public class TimerTask implements Task {<BR>    private static int count = 0;<BR>    private int num = count;<BR>    public TimerTask() {<BR>        count++;<BR>    }<BR>    public void <STRONG><FONT color=#0000ff>execute</FONT></STRONG>() {<BR>        System.out.println("[TimerTask " + num + "] start...");<BR>        try {<BR>            Thread.sleep(2000);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>        System.out.println("[TimerTask " + num + "] done.");<BR>    }<BR>}</P> <P>以上d均简单的sleep若干U?/P> <P>TaskQueue实现了一个队列,客户端可以将h攑օ队列Q服务器U程可以从队列中取出dQ?/P> <P>package com.crackj2ee.thread;<BR>import java.util.*;<BR>public class TaskQueue {<BR>    private List queue = new LinkedList();<BR>    public synchronized Task <STRONG><FONT color=#ff0000>getTask</FONT></STRONG>() {<BR>        while(queue.size()==0) {<BR>            try {<BR>                this.wait();<BR>            }<BR>            catch(InterruptedException ie) {<BR>                return null;<BR>            }<BR>        }<BR>        return (Task)queue.remove(0);<BR>    }<BR>    public synchronized void <FONT color=#ff0000><STRONG>putTask</STRONG></FONT>(Task task) {<BR>        queue.add(task);<BR>        this.notifyAll();<BR>    }<BR>}</P> <P>l于C真正的WorkerThreadQ这是真正执行Q务的服务器线E:</P> <P>package com.crackj2ee.thread;<BR>public class WorkerThread extends Thread {<BR>    private static int count = 0;<BR>    private boolean busy = false;<BR>    private boolean stop = false;<BR>    private TaskQueue queue;<BR>    public WorkerThread(ThreadGroup group, TaskQueue queue) {<BR>        super(group, "worker-" + count);<BR>        count++;<BR>        this.queue = queue;<BR>    }<BR>    public void shutdown() {<BR>        stop = true;<BR>        this.interrupt();<BR>        try {<BR>            this.join();<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR>    public boolean isIdle() {<BR>        return !busy;<BR>    }<BR>    public void run() {<BR>        System.out.println(getName() + " start.");        <BR>        while(!stop) {<BR>            Task task = <FONT color=#ff0000><STRONG>queue.getTask();</STRONG></FONT><BR>            if(task!=null) {<BR>                busy = true;<BR>                task.execute();<BR>                busy = false;<BR>            }<BR>        }<BR>        System.out.println(getName() + " end.");<BR>    }<BR>}</P> <P>前面已经讲过Qqueue.getTask()是一个阻塞方法,服务器线E可能在此wait()一D|间。此外,W(xu)orkerThreadq有一个shutdownҎ(gu)Q用于安全结束线E?/P> <P>最后是ThreadPoolQ负责管理所有的服务器线E,q可以动态增加和减少U程敎ͼ</P> <P>package com.crackj2ee.thread;<BR>import java.util.*;<BR>public class ThreadPool extends ThreadGroup {<BR>    private List threads = new LinkedList();<BR>    private TaskQueue queue;<BR>    public ThreadPool(TaskQueue queue) {<BR>        super("Thread-Pool");<BR>        this.queue = queue;<BR>    }<BR>    public synchronized void addWorkerThread() {<BR>        Thread t = new WorkerThread(this, queue);<BR>        threads.add(t);<BR>        t.start();<BR>    }<BR>    public synchronized void removeWorkerThread() {<BR>        if(threads.size()>0) {<BR>            WorkerThread t = (WorkerThread)threads.remove(0);<BR>            t.shutdown();<BR>        }<BR>    }<BR>    public synchronized void <FONT color=#ff0000><STRONG>currentStatus</STRONG></FONT>() {<BR>        System.out.println("-----------------------------------------------");<BR>        System.out.println("Thread count = " + threads.size());<BR>        Iterator it = threads.iterator();<BR>        while(it.hasNext()) {<BR>            WorkerThread t = (WorkerThread)it.next();<BR>            System.out.println(t.getName() + ": " + (t.isIdle() ? "idle" : "busy"));<BR>        }<BR>        System.out.println("-----------------------------------------------");<BR>    }<BR>}</P> <P>currentStatus()Ҏ(gu)是ؓ了方便调试,打印出所有线E的当前状态?/P> <P>最后,Main负责完成main()Ҏ(gu)Q?/P> <P>package com.crackj2ee.thread;<BR>public class Main {<BR>    public static void main(String[] args) {<BR>        TaskQueue queue = new TaskQueue();<BR>        ThreadPool pool = new ThreadPool(queue);<BR>        for(int i=0; i<10; i++) {<BR>            queue.putTask(new CalculateTask());<BR>            queue.putTask(new TimerTask());<BR>        }<BR>        pool.addWorkerThread();<BR>        pool.addWorkerThread();<BR>        doSleep(8000);<BR>        pool.currentStatus();<BR>        pool.addWorkerThread();<BR>        pool.addWorkerThread();<BR>        pool.addWorkerThread();<BR>        pool.addWorkerThread();<BR>        pool.addWorkerThread();<BR>        doSleep(5000);<BR>        pool.currentStatus();<BR>    }<BR>    private static void doSleep(long ms) {<BR>        try {<BR>            Thread.sleep(ms);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR>}</P> <P>main()一开始放入了20个TaskQ然后动态添加了一些服务线E,q定期打印线E状态,q行l果如下Q?/P> <P>worker-0 start.<BR>[CalculateTask 0] start...<BR>worker-1 start.<BR>[TimerTask 0] start...<BR>[TimerTask 0] done.<BR>[CalculateTask 1] start...<BR>[CalculateTask 0] done.<BR>[TimerTask 1] start...<BR>[CalculateTask 1] done.<BR>[CalculateTask 2] start...<BR>[TimerTask 1] done.<BR>[TimerTask 2] start...<BR>[TimerTask 2] done.<BR>[CalculateTask 3] start...<BR>-----------------------------------------------<BR>Thread count = 2<BR>worker-0: busy<BR>worker-1: busy<BR>-----------------------------------------------<BR>[CalculateTask 2] done.<BR>[TimerTask 3] start...<BR>worker-2 start.<BR>[CalculateTask 4] start...<BR>worker-3 start.<BR>[TimerTask 4] start...<BR>worker-4 start.<BR>[CalculateTask 5] start...<BR>worker-5 start.<BR>[TimerTask 5] start...<BR>worker-6 start.<BR>[CalculateTask 6] start...<BR>[CalculateTask 3] done.<BR>[TimerTask 6] start...<BR>[TimerTask 3] done.<BR>[CalculateTask 7] start...<BR>[TimerTask 4] done.<BR>[TimerTask 7] start...<BR>[TimerTask 5] done.<BR>[CalculateTask 8] start...<BR>[CalculateTask 4] done.<BR>[TimerTask 8] start...<BR>[CalculateTask 5] done.<BR>[CalculateTask 9] start...<BR>[CalculateTask 6] done.<BR>[TimerTask 9] start...<BR>[TimerTask 6] done.<BR>[TimerTask 7] done.<BR>-----------------------------------------------<BR>Thread count = 7<BR><STRONG><FONT color=#008080>worker-0: idle<BR></FONT></STRONG>worker-1: busy<BR>worker-2: busy<BR><STRONG><FONT color=#008080>worker-3: idle</FONT></STRONG><BR>worker-4: busy<BR>worker-5: busy<BR>worker-6: busy<BR>-----------------------------------------------<BR>[CalculateTask 7] done.<BR>[CalculateTask 8] done.<BR>[TimerTask 8] done.<BR>[TimerTask 9] done.<BR>[CalculateTask 9] done.</P> <P><STRONG>仔细观察</STRONG>Q一开始只有两个服务器U程Q因此线E状态都是忙Q后来线E数增多Q?个线E中的两个状态变成idleQ说明处于wait()状态?/P> <P><FONT color=#ff0000><STRONG>思?/STRONG></FONT>Q本例的U程调度法其实Ҏ(gu)没有Q因个应用是围绕TaskQueue设计的,不是以Thread PoolZ心设计的。因此,Task调度取决于TaskQueue的getTask()Ҏ(gu)Q你可以改进q个Ҏ(gu)Q例如用优先队列,使优先高的d先被执行?/P> <P>如果所有的服务器线E都处于busy状态,则说明Q务繁忙,TaskQueue的队列越来越长,最l会D服务器内存耗尽。因此,可以限制 TaskQueue的等待Q务数Q超q最大长度就拒绝处理。许多Web服务器在用户hJ忙时就会拒l用PHTTP 503 SERVICE UNAVAILABLE<BR></P> <P>多线E读写同一个对象的数据是很普遍的,通常Q要避免d冲突Q必M证Q何时候仅有一个线E在写入Q有U程正在d的时候,写入操作必ȝ待。简单说Q就是要避免“写-写”冲H和“读-写”冲H。但是同时读是允许的Q因为“读-诠Z不冲突Q而且很安全?/P> <P>要实C上的ReadWriteLockQ简单的使用synchronized׃行,我们必须自己设计一个ReadWriteLockc,在读之前Q必d获得“读锁”,写之前,必须先获得“写锁”。D例说明:</P> <P>DataHandler对象保存了一个可d的char[]数组Q?/P> <P>package com.crackj2ee.thread;<BR><BR>public class DataHandler {<BR>    // store data:<BR>    private char[] buffer = "AAAAAAAAAA".toCharArray();<BR><BR>    private char[] doRead() {<BR>        char[] ret = new char[buffer.length];<BR>        for(int i=0; i<buffer.length; i++) {<BR>            ret[i] = buffer[i];<BR>            sleep(3);<BR>        }<BR>        return ret;<BR>    }<BR><BR>    private void doWrite(char[] data) {<BR>        if(data!=null) {<BR>            buffer = new char[data.length];<BR>            for(int i=0; i<buffer.length; i++) {<BR>                buffer[i] = data[i];<BR>                sleep(10);<BR>            }<BR>        }<BR>    }<BR><BR>    private void sleep(int ms) {<BR>        try {<BR>            Thread.sleep(ms);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR>}</P> <P>doRead()和doWrite()Ҏ(gu)是非U程安全的读写方法。ؓ了演C,加入了sleep()Qƈ讄ȝ速度大约是写?倍,q符合通常的情c?/P> <P>Z让多U程能安全读写,我们设计了一个ReadWriteLockQ?/P> <P>package com.crackj2ee.thread;<BR>public class ReadWriteLock {<BR>    private int readingThreads = 0;<BR>    private int writingThreads = 0;<BR>    private int waitingThreads = 0; // waiting for write<BR>    private boolean preferWrite = true;<BR><BR>    public synchronized void readLock() throws InterruptedException {<BR>        while(writingThreads>0 || (preferWrite && waitingThreads>0))<BR>            this.wait();<BR>        readingThreads++;<BR>    }<BR><BR>    public synchronized void readUnlock() {<BR>        readingThreads--;<BR>        preferWrite = true;<BR>        notifyAll();<BR>    }<BR><BR>    public synchronized void writeLock() throws InterruptedException {<BR>        waitingThreads++;<BR>        try {<BR>            while(readingThreads>0 || writingThreads>0)<BR>                this.wait();<BR>        }<BR>        finally {<BR>            waitingThreads--;<BR>        }<BR>        writingThreads++;<BR>    }<BR><BR>    public synchronized void writeUnlock() {<BR>        writingThreads--;<BR>        preferWrite = false;<BR>        notifyAll();<BR>    }<BR>}</P> <P>readLock()用于获得读锁QreadUnlock()释放读锁QwriteLock()和writeUnlock()一栗由于锁用完必须释放Q因此,必须保证lock和unlock匚w。我们修改DataHandlerQ加入ReadWriteLockQ?/P> <P>package com.crackj2ee.thread;<BR>public class DataHandler {<BR>    // store data:<BR>    private char[] buffer = "AAAAAAAAAA".toCharArray();<BR>    // lock:<BR>    private ReadWriteLock lock = new ReadWriteLock();<BR><BR>    public char[] read(String name) throws InterruptedException {<BR>        System.out.println(name + " waiting for read...");<BR>        <STRONG><FONT color=#ff0000>lock.readLock();</FONT></STRONG><BR>        try {<BR>            char[] data = doRead();<BR>            System.out.println(name + " reads data: " + new String(data));<BR>            return data;<BR>        }<BR>        finally {<BR>            <STRONG><FONT color=#ff0000>lock.readUnlock();<BR></FONT></STRONG>        }<BR>    }<BR><BR>    public void write(String name, char[] data) throws InterruptedException {<BR>        System.out.println(name + " waiting for write...");<BR>        <STRONG><FONT color=#ff0000>lock.writeLock();<BR></FONT></STRONG>        try {<BR>            System.out.println(name + " wrote data: " + new String(data));<BR>            doWrite(data);<BR>        }<BR>        finally {<BR>            <STRONG><FONT color=#ff0000>lock.writeUnlock();<BR></FONT></STRONG>        }<BR>    }<BR><BR>    private char[] doRead() {<BR>        char[] ret = new char[buffer.length];<BR>        for(int i=0; i<buffer.length; i++) {<BR>            ret[i] = buffer[i];<BR>            sleep(3);<BR>        }<BR>        return ret;<BR>    }<BR>    private void doWrite(char[] data) {<BR>        if(data!=null) {<BR>            buffer = new char[data.length];<BR>            for(int i=0; i<buffer.length; i++) {<BR>                buffer[i] = data[i];<BR>                sleep(10);<BR>            }<BR>        }<BR>    }<BR>    private void sleep(int ms) {<BR>        try {<BR>            Thread.sleep(ms);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR>}</P> <P>publicҎ(gu)read()和write()完全装了底层的ReadWriteLockQ因此,多线E可以安全地调用q两个方法:</P> <P>// ReadingThread不断d数据Q?BR>package com.crackj2ee.thread;<BR>public class ReadingThread extends Thread {<BR>    private DataHandler handler;<BR>    public ReadingThread(DataHandler handler) {<BR>        this.handler = handler;<BR>    }<BR>    public void run() {<BR>        for(;;) {<BR>            try {<BR>                char[] data = handler.read(getName());<BR>                Thread.sleep((long)(Math.random()*1000+100));<BR>            }<BR>            catch(InterruptedException ie) {<BR>                break;<BR>            }<BR>        }<BR>    }<BR>}</P> <P>// WritingThread不断写入数据Q每ơ写入的都是10个相同的字符Q?BR>package com.crackj2ee.thread;<BR>public class WritingThread extends Thread {<BR>    private DataHandler handler;<BR>    public WritingThread(DataHandler handler) {<BR>        this.handler = handler;<BR>    }<BR>    public void run() {<BR>        char[] data = new char[10];<BR>        for(;;) {<BR>            try {<BR>                fill(data);<BR>                handler.write(getName(), data);<BR>                Thread.sleep((long)(Math.random()*1000+100));<BR>            }<BR>            catch(InterruptedException ie) {<BR>                break;<BR>            }<BR>        }<BR>    }<BR>    // 产生一个A-Z随机字符Q填入char[10]:<BR>    private void fill(char[] data) {<BR>        char c = (char)(Math.random()*26+'A');<BR>        for(int i=0; i<data.length; i++)<BR>            data[i] = c;<BR>    }<BR>}</P> <P>最后Main负责启动q些U程Q?/P> <P>package com.crackj2ee.thread;<BR>public class Main {<BR>    public static void main(String[] args) {<BR>        DataHandler handler = new DataHandler();<BR>        Thread[] ts = new Thread[] {<BR>                new ReadingThread(handler),<BR>                new ReadingThread(handler),<BR>                new ReadingThread(handler),<BR>                new ReadingThread(handler),<BR>                new ReadingThread(handler),<BR>                new WritingThread(handler),<BR>                new WritingThread(handler)<BR>        };<BR>        for(int i=0; i<ts.length; i++) {<BR>            ts[i].start();<BR>        }<BR>    }<BR>}</P> <P>我们启动?个读U程?个写U程Q运行结果如下:</P> <P><FONT face="Courier New">Thread-0 waiting for read...<BR>Thread-1 waiting for read...<BR>Thread-2 waiting for read...<BR>Thread-3 waiting for read...<BR>Thread-4 waiting for read...<BR>Thread-5 waiting for write...<BR>Thread-6 waiting for write...<BR>Thread-4 reads data: AAAAAAAAAA<BR>Thread-3 reads data: AAAAAAAAAA<BR>Thread-2 reads data: AAAAAAAAAA<BR>Thread-1 reads data: AAAAAAAAAA<BR>Thread-0 reads data: AAAAAAAAAA<BR>Thread-5 wrote data: EEEEEEEEEE<BR>Thread-6 wrote data: MMMMMMMMMM<BR>Thread-1 waiting for read...<BR>Thread-4 waiting for read...<BR>Thread-1 reads data: MMMMMMMMMM<BR>Thread-4 reads data: MMMMMMMMMM<BR>Thread-2 waiting for read...<BR>Thread-2 reads data: MMMMMMMMMM<BR>Thread-0 waiting for read...<BR>Thread-0 reads data: MMMMMMMMMM<BR>Thread-4 waiting for read...<BR>Thread-4 reads data: MMMMMMMMMM<BR>Thread-2 waiting for read...<BR>Thread-5 waiting for write...<BR>Thread-2 reads data: MMMMMMMMMM<BR>Thread-5 wrote data: GGGGGGGGGG<BR>Thread-6 waiting for write...<BR>Thread-6 wrote data: AAAAAAAAAA<BR>Thread-3 waiting for read...<BR>Thread-3 reads data: AAAAAAAAAA<BR>......</FONT></P> <P>可以看到Q每ơ读/写都是完整的原子操作Q因为我们每ơ写入的都是10个相同字W。ƈ且,每次d的都是最q一ơ写入的内容?/P> <P>如果LReadWriteLockQ?/P> <P>package com.crackj2ee.thread;<BR>public class DataHandler {<BR><BR>    // store data:<BR>    private char[] buffer = "AAAAAAAAAA".toCharArray();<BR><BR>    public char[] read(String name) throws InterruptedException {<BR>        char[] data = doRead();<BR>        System.out.println(name + " reads data: " + new String(data));<BR>        return data;<BR>    }<BR>    public void write(String name, char[] data) throws InterruptedException {<BR>        System.out.println(name + " wrote data: " + new String(data));<BR>        doWrite(data);<BR>    }<BR><BR>    private char[] doRead() {<BR>        char[] ret = new char[10];<BR>        for(int i=0; i<10; i++) {<BR>            ret[i] = buffer[i];<BR>            sleep(3);<BR>        }<BR>        return ret;<BR>    }<BR>    private void doWrite(char[] data) {<BR>        for(int i=0; i<10; i++) {<BR>            buffer[i] = data[i];<BR>            sleep(10);<BR>        }<BR>    }<BR>    private void sleep(int ms) {<BR>        try {<BR>            Thread.sleep(ms);<BR>        }<BR>        catch(InterruptedException ie) {}<BR>    }<BR>}</P> <P>q行l果如下Q?/P> <P><FONT face="Courier New">Thread-5 wrote data: AAAAAAAAAA<BR>Thread-6 wrote data: MMMMMMMMMM<BR>Thread-0 reads data: AAAAAAAAAA<BR>Thread-1 reads data: AAAAAAAAAA<BR>Thread-2 reads data: AAAAAAAAAA<BR>Thread-3 reads data: AAAAAAAAAA<BR>Thread-4 reads data: AAAAAAAAAA<BR>Thread-2 reads data: MAAAAAAAAA<BR>Thread-3 reads data: MAAAAAAAAA<BR>Thread-5 wrote data: CCCCCCCCCC<BR>Thread-1 reads data: MAAAAAAAAA<BR>Thread-0 reads data: MAAAAAAAAA<BR>Thread-4 reads data: MAAAAAAAAA<BR></FONT><STRONG><FONT face="Courier New" color=#ff0000>Thread-6 wrote data: EEEEEEEEEE<BR>Thread-3 reads data: EEEEECCCCC<BR>Thread-4 reads data: EEEEEEEEEC<BR>Thread-1 reads data: EEEEEEEEEE</FONT></STRONG></P> <P>可以看到在Thread-6写入EEEEEEEEEE的过E中Q?个线E读取的内容是不同的?/P> <P><FONT color=#ff0000><STRONG>思?/STRONG></FONT></P> <P>java的synchronized提供了最底层的物理锁Q要在synchronized的基上,实现自己的逻辑锁,必Ml设计ReadWriteLock?/P> <P>Q: lock.readLock()Z么不攑օtry{ } 内?<BR>A: 因ؓreadLock()会抛出InterruptedExceptionQ导致readingThreads++不执行,而readUnlock()?finally{ } 中,DreadingThreads--执行Q从而readingThread状态出错。writeLock()也是cM的?/P> <P>Q: preferWrite有用吗?<BR>A: 如果LpreferWriteQ线E安全不受媄响。但是,如果dU程很多Q上一个线E还没有d完,下一个线E又开始读了,导致写入线E长旉无法获得writeLockQ如果写入线E等待的很多Q一个接一个写Q也会导致读取线E长旉无法获得readLock。preferWrite的作用是让读 /写交替执行,避免׃ȝE繁忙导致写无法q行和由于写U程J忙DL法进行?/P> <P>Q: notifyAll()换成notify()行不行?<BR>A: 不可以。由于preferWrite的存在,如果一个线E刚d完毕Q此时preferWrite=trueQ再notify()Q若恰好唤醒的是一个读U程Q则while(writingThreads>0 || (preferWrite && waitingThreads>0))可能为trueD该读U程l箋{待Q而等待写入的U程也处于wait()中,l果所有线E都处于wait ()状态,谁也无法唤醒谁。因此,notifyAll()比notify()要来得安全。程序验证notify()带来的死锁:</P> <P><FONT face="Courier New">Thread-0 waiting for read...<BR>Thread-1 waiting for read...<BR>Thread-2 waiting for read...<BR>Thread-3 waiting for read...<BR>Thread-4 waiting for read...<BR>Thread-5 waiting for write...<BR>Thread-6 waiting for write...<BR>Thread-0 reads data: AAAAAAAAAA<BR>Thread-4 reads data: AAAAAAAAAA<BR>Thread-3 reads data: AAAAAAAAAA<BR>Thread-2 reads data: AAAAAAAAAA<BR>Thread-1 reads data: AAAAAAAAAA<BR>Thread-5 wrote data: CCCCCCCCCC<BR>Thread-2 waiting for read...<BR>Thread-1 waiting for read...<BR>Thread-3 waiting for read...<BR>Thread-0 waiting for read...<BR>Thread-4 waiting for read...<BR>Thread-6 wrote data: LLLLLLLLLL<BR>Thread-5 waiting for write...<BR>Thread-6 waiting for write...<BR>Thread-2 reads data: LLLLLLLLLL<BR>Thread-2 waiting for read...<BR>Q运行到此不动了Q?/FONT></P> <P>注意到这U死锁是׃所有线E都在等待别的线E唤醒自己,l果都无法醒q来。这和两个线E希望获得对方已有的锁造成死锁不同。因此多U程设计的难度远q高于单U程应用?/P><img src ="http://www.aygfsteel.com/iNeo/aggbug/23754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/iNeo/" target="_blank">只牵q只?/a> 2005-12-14 08:54 <a href="http://www.aygfsteel.com/iNeo/articles/23754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在不容许使用W三个变量下Q实C个函敎ͼ把两个整型参数的值对?http://www.aygfsteel.com/iNeo/articles/21551.html只牵q只?/dc:creator>只牵q只?/author>Sun, 27 Nov 2005 04:43:00 GMThttp://www.aygfsteel.com/iNeo/articles/21551.htmlhttp://www.aygfsteel.com/iNeo/comments/21551.htmlhttp://www.aygfsteel.com/iNeo/articles/21551.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/21551.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/21551.htmlswap(int a, int b)
{
  a -= b;  // a(new) = a-b
  b += a;  // b(new) = b+a(new) = b+(a-b)=a
  a = b-a;  // a(result) = b-a(new)= a-(a-b)=b
}

解答?
b=(a=(b=(a^b))^a)^b

解答?
a = a^(a^b);
b = b^(a^b);



]]>
վ֩ģ壺 Ԫ| Ӷ| | | ʯ̨| | Դ| ɽ| | Ͽ| | | ɽ| ̩| | Ϫ| | ϽϽ| ͨ| ̩| | ɽ| | | | | ɽ| ̨| ɽ| 㽭ʡ| ƽ| | | ˳| | ƺ| пѷ| ɽ| | Ϣ| н|