1.在D:\>java Dome 下面那行是源码什么意思
2.解读useEffectåuseLayouEffectåç
3.k8s要学多久
4.Javaä¸RunnableåThreadçåºå«
在D:\>java Dome 下面那行是什么意思
出现异常了,说你的源码Dome这个类没有定义。你检查一下是源码不是引用错了。
还有一个可能是源码你源代码里的class为Demo,但是源码你的文件名里面是Dome。你检查一下是源码delphi lis源码不是这里写错了。
解读useEffectåuseLayouEffectåç
èæ¯
åè¿ç¯æç« æ¯å 为工ä½ä¸ä¸æ¯é常ç¹å¿ï¼å¯ä»¥æ½ç©ºå¦ä¹ èªå·±å¸¸ç¨æ¡æ¶åç±»åºï¼æ·±å ¥ç解å®ä»¬ï¼å¨ææ¯ä¸å¸æææ´å¤§çè¿æ¥ï¼å¹å »å¦ä¹ å ´è¶£ï¼
useEffectåå ¶å®hooksä¸æ ·ï¼å è½½åæ´æ°æ§è¡ä¸ä¸æ ·çæ¹æ³(mountEffectåupdateEffect)ï¼
1.mountEffect页é¢å è½½æ¶ï¼æ§è¡mountEffectï¼
å建hook对象ï¼å å ¥ç»ä»¶çhookååé¾è¡¨ï¼
å¨ç»ä»¶çfiberçflagä¸å å ¥å¯ä½ç¨ç¸å ³çeffectTagï¼(å è½½æé´é»è®¤ælayoutEffectåeffectçå¯ä½ç¨)
å建effect对象ï¼ç»hook对象çmemoizedStateåå å ¥ç»ä»¶fiberçupdateQueueä¸å½¢æeffectç¯ç¶é¾è¡¨ï¼å¨æ¸²æå·¥ä½å®æåï¼ä¼å¾ªç¯è¿ä¸ªç¯ç¶é¾è¡¨ï¼æ§è¡æ¯ä¸ªeffect对象çdestoryåcreateï¼
consteffect={ tag,源码create,destroy,deps,next:null};tagæ¯effectçç±»åtag为9æ¯useEffect,5æ¯useLayoutEffectcreateæ¯useEffectæuseLayoutEffectçåè°å½æ°destroyæ¯createè¿åçåè°å½æ°depsæ¯useEffectæuseLayoutEffectçä¾èµæ°ç»nextæåä¸ä¸ªeffect对象ï¼1.1.effectç¯ç¶é¾è¡¨å¾functionpushEffect(tag,create,destroy,deps){ consteffect={ tag,create,destroy,deps,next:null};//æ°å建çeffect对象为æå为effecté¾è¡¨çä¸ä¸ªeffect对象ï¼componentUpdateQueue.lastEffectä¼æåæ°å建çeffect对象//æ°å建çeffect对象çnextä¼æå第ä¸ä¸ªeffct对象ï¼letcomponentUpdateQueue=(currentlyRenderingFiber.updateQueue);if(componentUpdateQueue===null){ //å½å没æupdateQueuecomponentUpdateQueue=createFunctionComponentUpdateQueue();//å建updateQueuecurrentlyRenderingFiber.updateQueue=componentUpdateQueue;//å½¢æä¸ä¸ªç¯ç¶é¾è¡¨componentUpdateQueue.lastEffect=effect.next=effect}else{ constlastEffect=componentUpdateQueue.lastEffect;if(lastEffect===null){ componentUpdateQueue.lastEffect=effect.next=effect;}else{ //第ä¸ä¸ªeffect对象为æå å建ççeffect对象constfirstEffect=lastEffect.next;//è·å第ä¸ä¸ªeffect对象lastEffect.next=effect;//æ§çæåä¸ä¸ªeffect对象çnextï¼æåæ°å建çeffecteffect.next=firstEffect;//æ°å建çeffect对象çnextæå第ä¸ä¸ªeffectcomponentUpdateQueue.lastEffect=effect;//updateQueueçlastEffectæåeffectï¼æ°å建çeffectå为æåä¸ä¸ªeffect对象}}returneffect;}2.updateEffect页é¢æ´æ°æ¶ï¼æ§è¡updateEffect;
æ ¹æ®hookååé¾è¡¨è·å对åºçæ´æ°æ¶çhook对象ï¼å建æ°çhook对象ï¼å å ¥hookååé¾è¡¨ï¼
å¦æeffectçdepsä¸ä¸ºnullï¼æè undefinedï¼ä¼ä»å½åhook对象æ¿å°ä¸ä¸æ¬¡effect对象ï¼åä»effect对象æ¿å°depsådestroyï¼ç¨æ°çdepsä¸ä¹æ¯è¾ï¼
å¦ææ°èdepsç¸çï¼pushä¸ä¸ªä¸å¸¦HookHasEffectçtagç»effect对象ï¼å å ¥updateQueueç¯ç¶é¾è¡¨ï¼è¿ä¸ªeffectä¸ä¼è¢«æ 记为æå¯ä½ç¨ï¼æ以ï¼effectçcreateådestroyä¸ä¼è¢«æ§è¡ï¼ï¼ä¸æ´æ°hook.memoizedStateï¼
å¦ææ°èdepsä¸ç¸çï¼æ´æ°effect对象ï¼å¨effectçtagä¸å å ¥HookHasEffectåä¸ä¸æ¬¡createæ§è¡çdestroyï¼æ´æ°hook.memoizedState;
3.useEffctçåè°å½æ°åéæ¯å½æ°çæ§è¡æ¶æºå¨renderæ¶ææ建effecté¾è¡¨ï¼å¨commitæ¶æ§è¡å æ§è¡ä¹å没ææ§è¡å®çuseEffectï¼ç¶åï¼å¨beforeMutationé¶æ®µæä½domåï¼ä»¥NormalPriority常è§ä¼å 级添å ä¸ä¸ªå¼æ¥ä»»å¡å°ä»»å¡éåï¼è¿ä¸ªå¼æ¥ä»»å¡æ¯ç¨æ¥æ§è¡useEffectçdestroyåcreateçï¼ï¼å¨layouté¶æ®µå®æï¼é¡µé¢å®æ渲æåï¼æ§è¡å¨beforeMutationé¶æ®µæ·»å çå¼æ¥ä»»å¡ï¼
3.1.commitå¼å§æ¶ä¸»è¦æ¯ä¸ºäºæ§è¡ä¹å没ææ§è¡çuseEffect
è¿å ¥commité¶æ®µï¼è¿åuseEffectå¼æ¥è°åº¦çç¹ç¹æå ³ï¼å®ä»¥ä¸è¬çä¼å 级被è°åº¦ï¼æå³çä¸æ¦ææ´é«ä¼å 级çä»»å¡è¿å ¥å°commité¶æ®µï¼ä¸ä¸æ¬¡ä»»å¡çuseEffectè¿æ²¡å¾å°æ§è¡ãæ以å¨æ¬æ¬¡æ´æ°å¼å§åï¼éè¦å å°ä¹åçuseEffecté½æ§è¡æï¼ä»¥ä¿è¯æ¬æ¬¡è°åº¦çuseEffecté½æ¯æ¬æ¬¡æ´æ°äº§ççã
functioncommitRootImpl(root,recoverableErrors,renderPriorityLevel){ do{ //`flushPassiveEffects`willcall`flushSyncUpdateQueue`attheend,which//means`flushPassiveEffects`willsometimesresultinadditional//passiveeffects.Soweneedtokeepflushinginaloopuntilthereare//nomorependingeffects.//TODO:Mightbebetterif`flushPassiveEffects`didnotautomatically//flushsynchronousworkattheend,toavoidfactoringhazardslikethis.flushPassiveEffects();}while(rootWithPendingPassiveEffects!==null);...çç¥ä»£ç }3.2.beforeMutationåªä¼åèµ·ä¸æ¬¡useEffectè°åº¦ï¼æ¯å¼æ¥è°åº¦ï¼ä»¥NormalPriority常è§ä¼å 级添å ä¸ä¸ªå¼æ¥ä»»å¡å¨ä»»å¡éåä¸ï¼push(timerQueue,newTask)ï¼ï¼å¨é¡µé¢æ¸²æå®ææ¶ï¼ä¼æ§è¡è¿ä¸ªå¼æ¥ä»»å¡
functioncommitRootImpl(root,recoverableErrors,renderPriorityLevel){ ...çç¥ä»£ç if((finishedWork.subtreeFlags&PassiveMask)!==NoFlags||(finishedWork.flags&PassiveMask)!==NoFlags){ if(!rootDoesHavePassiveEffects){ rootDoesHavePassiveEffects=true;scheduleCallback$1(NormalPriority,function(){ //æ·»å ä¸ä¸ªå¼æ¥ä»»å¡å°ä»»å¡éåflushPassiveEffects();//Thisrendertriggeredpassiveeffects:releasetherootcachepool//*after*passiveeffectsfiretoavoidfreeingacachepoolthatmay//bereferencedbyanodeinthetree(HostRoot,Cacheboundaryetc)returnnull;});}}...çç¥ä»£ç }3.3.layoutå è½½æ¶ï¼åªæ§è¡useEffectçcreateå½æ°å³å¯ï¼
å¦æpendingPassiveEffectsLanesæ¯åæ¥èµéï¼å°±å¨é¡µé¢æ¸²æå®ç´æ¥æ§è¡useEffectçcreateådestroyï¼å¨beforeMutationæ¶æ·»å çå¼æ¥ä»»å¡ï¼ä¸ä¼æ§è¡useEffectçcreateådestory
if(includesSomeLane(pendingPassiveEffectsLanes,SyncLane)&&root.tag!==LegacyRoot){ //å è½½æé´é»è®¤æ¯ä¸èµ°è¿éç//è¿éä¹æ¯æ§è¡useEffectçcreateï¼å¦æpendingPassiveEffectsLanesæ¯åæ¥èµéï¼//å°±å¨æ¸²æå®æåç´æ¥æ§è¡useEffectçcreateådestory//å¨beforeMutationæ¶æ·»å çå¼æ¥ä»»å¡æ§è¡æ¶ï¼ä¸ä¼æ§è¡useEffectçcreateådestoryflushPassiveEffects();}æ§è¡ä¸ä¸æ¬¡useEffectçcreateè¿åçdestroyï¼æ¿å°å½æ°ç»ä»¶fiberçupdateQueueï¼å¾ªç¯è¿ä¸ªeffectç¯ç¶é¾è¡¨ï¼æ¿å°effect对象çdestroyæ§è¡ï¼
functioncommitHookEffectListUnmount(flags,finishedWork,nearestMountedAncestor){ varupdateQueue=finishedWork.updateQueue;varlastEffect=updateQueue!==null?updateQueue.lastEffect:null;if(lastEffect!==null){ varfirstEffect=lastEffect.next;vareffect=firstEffect;do{ if((effect.tag&flags)===flags){ //Unmountvardestroy=effect.destroy;effect.destroy=undefined;if(destroy!==undefined){ { if((flags&Passive$1)!==NoFlags$1){ markComponentPassiveEffectUnmountStarted(finishedWork);}elseif((flags&Layout)!==NoFlags$1){ markComponentLayoutEffectUnmountStarted(finishedWork);}}safelyCallDestroy(finishedWork,nearestMountedAncestor,destroy);//æ§è¡destroy{ if((flags&Passive$1)!==NoFlags$1){ markComponentPassiveEffectUnmountStopped();}elseif((flags&Layout)!==NoFlags$1){ markComponentLayoutEffectUnmountStopped();}}}}effect=effect.next;}while(effect!==firstEffect);}}æ§è¡å®ææç»ä»¶çdestroyï¼åæ§è¡createï¼åçï¼ä¹æ¯æ¿å°å½æ°ç»ä»¶fiberçupdateQueueï¼å¾ªç¯è¿ä¸ªeffectç¯ç¶é¾è¡¨ï¼æ¿å°effect对象çcreateæ§è¡ï¼ç¶åæcreateè¿åçdestroyç»effect对象ï¼ççä¸çæ´æ°æ§è¡useEffectæ¶ç¨ï¼ï¼
functioncommitHookEffectListMount(flags,finishedWork){ varupdateQueue=finishedWork.updateQueue;varlastEffect=updateQueue!==null?updateQueue.lastEffect:null;if(lastEffect!==null){ varfirstEffect=lastEffect.next;vareffect=firstEffect;do{ if((effect.tag&flags)===flags){ { if((flags&Passive$1)!==NoFlags$1){ markComponentPassiveEffectMountStarted(finishedWork);}elseif((flags&Layout)!==NoFlags$1){ markComponentLayoutEffectMountStarted(finishedWork);}}//Mountvarcreate=effect.create;effect.destroy=create();{ if((flags&Passive$1)!==NoFlags$1){ markComponentPassiveEffectMountStopped();}elseif((flags&Layout)!==NoFlags$1){ markComponentLayoutEffectMountStopped();}}{ vardestroy=effect.destroy;if(destroy!==undefined&&typeofdestroy!=='function'){ varhookName=void0;if((effect.tag&Layout)!==NoFlags){ hookName='useLayoutEffect';}elseif((effect.tag&Insertion)!==NoFlags){ hookName='useInsertionEffect';}else{ hookName='useEffect';}varaddendum=void0;if(destroy===null){ addendum='Youreturnednull.Ifyoureffectdoesnotrequireclean'+'up,returnundefined(ornothing).';}elseif(typeofdestroy.then==='function'){ addendum='\n\nItlookslikeyouwrote'+hookName+'(async()=>...)orreturnedaPromise.'+'Instead,writetheasyncfunctioninsideyoureffect'+'andcallitimmediately:\n\n'+hookName+'(()=>{ \n'+'asyncfunctionfetchData(){ \n'+'//Youcanawaithere\n'+'constresponse=awaitMyAPI.getData(someId);\n'+'//...\n'+'}\n'+'fetchData();\n'+"},[someId]);//Or[]ifeffectdoesn'tneedpropsorstate\n\n"+'LearnmoreaboutdatafetchingwithHooks:/post/k8s要学多久
学习Kubernetes的基础知识并不困难,特别是源码如果你已经有半个月的Docker使用经验。主要挑战在于封装镜像时需要考虑挂载、源码拆分和启动检测等问题。源码
安装Kubernetes本身就是源码一个复杂的过程。前期的源码安装尝试包括自动化安装、手动安装、源码webform网站源码脚本自动化安装、源码Ansible安装和离线安装,源码这耗费了我大约一个月的时间。随后,我遇到了一些环境和网络问题,导致pod一直重启,卸载程序 源码这个问题持续了大约两个月。我尝试更换为实体机,问题有所缓解,但最终估计还是网络不稳定导致。
学习kubectl命令和Kubernetes的基本组件(如pod、svc、android 收银源码deployment、daemonset、statefulset、headlessService、rc、kube-proxy、flash 交互源码rbac等)也是需要花费时间的。我花了大约一个月时间来理解这些组件的原理,尤其是新版本的rbac权限问题。Kubernetes的复杂性主要在于其体系架构,一旦理解了架构,就理解了大部分的内容。
在对开源工程domeos进行研究后,我使用了两个月时间来调研该开源工程的源码,以及它自带的一些小米open-falcon监控插件、webssh等插件。这些研究涉及使用Springboot开发,连接Kubernetes环境,部署和监控基本应用。
为了调优日志和监控,我又花费了一个多月的时间来调研一些开源产品,如efk日志插件、Prometheus与heaspter监控组件、habor镜像仓库等。
最后,我开始使用Helm这一编排工具,根据Hadoop的过程改造公司的一个mpp产品,并实现一键式部署。这同样花费了一个多月的时间。在这一过程中,我还研究了Hadoop的扩容、亲和性、带状态应用部署等问题,以及数据删除问题。
Javaä¸RunnableåThreadçåºå«
nableåthreadçåºå«ï¼å¤çº¿ç¨å¿ é¡»ç¨Runableï¼
Javaä¸æ两ç§å®ç°å¤çº¿ç¨çæ¹å¼ä»¥å两ç§æ¹å¼ä¹é´çåºå«
çå°ä¸ä¸ªé¢è¯é¢.é®ä¸¤ç§å®ç°å¤çº¿ç¨çæ¹æ³.没äºå»ç½ä¸æ¾äºæ¾çæ¡.
ç½ä¸æµä¼ å¾å¹¿çæ¯ä¸ä¸ªç½ä¸å®ç¥¨ç³»ç»è®²è§£.转åè¿æ¥.å·²ç»ä¸ç¥éåæå°åºæ¯åºèªåªéäº.
Javaä¸æ两ç§å®ç°å¤çº¿ç¨çæ¹å¼ãä¸æ¯ç´æ¥ç»§æ¿Threadç±»ï¼äºæ¯å®ç°Runnableæ¥å£ãé£ä¹è¿ä¸¤ç§å®ç°å¤çº¿ç¨çæ¹å¼å¨åºç¨ä¸æä»ä¹åºå«å¢ï¼
为äºåçè¿ä¸ªé®é¢ï¼æ们å¯ä»¥éè¿ç¼åä¸æ®µä»£ç æ¥è¿è¡åæãæ们ç¨ä»£ç æ¥æ¨¡æéè·¯å®ç¥¨ç³»ç»ï¼å®ç°éè¿å个å®ç¥¨ç¹åå®ææ¥æ次å车çå¼ è½¦ç¥¨ï¼ä¸ä¸ªå®ç¥¨ç¹ç¨ä¸ä¸ªçº¿ç¨è¡¨ç¤ºã
é¦å è¿æ ·ç¼åè¿ä¸ªç¨åºï¼
Java代ç
class ThreadTest extends Thread{
private int ticket = ;
public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
"is saling ticket" + ticket--);
}else{
break;
}
}
}
}
æºç æå°ï¼
class ThreadTest extends Thread{
private int ticket = ;
public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
"is saling ticket" + ticket--);
}else{
break;
}
}
}
}
mainæµè¯ç±»:
Java代ç
public class ThreadDome1{
public static void main(String[] args){
ThreadTest t = new ThreadTest();
t.start();
t.start();
t.start();
t.start();
}
}
æºç æå°ï¼
public class ThreadDome1{
public static void main(String[] args){
ThreadTest t = new ThreadTest();
t.start();
t.start();
t.start();
t.start();
}
}
ä¸é¢ç代ç ä¸ï¼æ们ç¨ThreadTest类模æå®ç¥¨å¤çå®ç¥¨è¿ç¨ï¼runæ¹æ³ä¸çæ¯ä¸æ¬¡å¾ªç¯é½å°æ»ç¥¨æ°å1ï¼æ¨¡æååºä¸å¼ 车票ï¼åæ¶è¯¥è½¦ç¥¨å·æå°åºæ¥ï¼ç´æ¥å©ä½ç票æ°å°é¶ä¸ºæ¢ãå¨ThreadDemo1ç±»çmainæ¹æ³ä¸ï¼æ们å建äºä¸ä¸ªçº¿ç¨å¯¹è±¡ï¼å¹¶éå¤å¯å¨å次ï¼å¸æéè¿è¿ç§æ¹å¼äº§çå个线ç¨ãä»è¿è¡çç»ææ¥çæ们åç°å ¶å®åªæä¸ä¸ªçº¿ç¨å¨è¿è¡ï¼è¿ä¸ªç»æ åè¯æ们ï¼ä¸ä¸ªçº¿ç¨å¯¹è±¡åªè½å¯å¨ä¸ä¸ªçº¿ç¨ï¼æ è®ºä½ è°ç¨å¤å°éstart()æ¹æ³ï¼ç»æåªæä¸ä¸ªçº¿ç¨ã
æ们æ¥çä¿®æ¹ThreadDemo1ï¼å¨mainæ¹æ³ä¸å建å个Thread对象ï¼
Java代ç
public class ThreadDemo1{
public static void main(String[] args){
new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
}
}
æºç æå°ï¼
public class ThreadDemo1{
public static void main(String[] args){
new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
new ThreadTest().start();
}
}
Java代ç
class ThreadTest extends Thread{
private int ticket = ;
public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket" + ticket--);
}else{
break;
}
}
}
}
æºç æå°ï¼
class ThreadTest extends Thread{
private int ticket = ;
public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket" + ticket--);
}else{
break;
}
}
}
}
è¿ä¸è¾¾å°ç®çäºåï¼
ä»ç»æä¸çæ¯ä¸ªç¥¨å·é½è¢«æå°äºå次ï¼å³ å个线ç¨åèªååèªçå¼ ç¥¨ï¼èä¸å»åå ±åçå¼ ç¥¨ãè¿ç§æ åµæ¯æä¹é æçå¢ï¼æ们éè¦çæ¯ï¼å¤ä¸ªçº¿ç¨å»å¤çåä¸ä¸ªèµæºï¼ä¸ä¸ªèµæºåªè½å¯¹åºä¸ä¸ªå¯¹è±¡ï¼å¨ä¸é¢çç¨åºä¸ï¼æ们å建äºå个ThreadTest对象ï¼å°±çäºå建äºå个èµæºï¼æ¯ä¸ªèµæºé½æå¼ ç¥¨ï¼æ¯ä¸ªçº¿ç¨é½å¨ç¬èªå¤çåèªçèµæºã
ç»è¿è¿äºå®éªååæï¼å¯ä»¥æ»ç»åºï¼è¦å®ç°è¿ä¸ªéè·¯å®ç¥¨ç¨åºï¼æ们åªè½å建ä¸ä¸ªèµæºå¯¹è±¡ï¼ä½è¦å建å¤ä¸ªçº¿ç¨å»å¤çåä¸ä¸ªèµæºå¯¹è±¡ï¼å¹¶ä¸æ¯ä¸ªçº¿ç¨ä¸æè¿è¡çæ¯ç¸åçç¨åºä»£ç ãå¨å顾ä¸ä¸ä½¿ç¨æ¥å£ç¼åå¤çº¿ç¨çè¿ç¨ã
Java代ç
public class ThreadDemo1{
public static void main(String[] args){
ThreadTest t = new ThreadTest();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
æºç æå°ï¼
public class ThreadDemo1{
public static void main(String[] args){
ThreadTest t = new ThreadTest();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
Java代ç
class ThreadTest implements Runnable{
private int tickets = ;
public void run(){
while(true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket " + tickets--);
}
}
}
}
æºç æå°ï¼
class ThreadTest implements Runnable{
private int tickets = ;
public void run(){
while(true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName() +
" is saling ticket " + tickets--);
}
}
}
}
ä¸é¢çç¨åºä¸ï¼å建äºå个线ç¨ï¼ æ¯ä¸ªçº¿ç¨è°ç¨çæ¯åä¸ä¸ªThreadTest对象ä¸çrun()æ¹æ³ï¼è®¿é®çæ¯åä¸ä¸ªå¯¹è±¡ä¸çåéï¼ticketsï¼çå®ä¾ï¼è¿ä¸ªç¨åºæ»¡è¶³äºæ们çéæ±ãå¨Windowsä¸å¯ä»¥å¯å¨å¤ä¸ªè®°äºæ¬ç¨åºä¸æ ·ï¼ä¹å°±æ¯å¤ä¸ªè¿ç¨ä½¿ç¨åä¸ä¸ªè®°äºæ¬ç¨åºä»£ç ã
å¯è§ï¼ å®ç°Runnableæ¥å£ç¸å¯¹äºç»§æ¿Threadç±»æ¥è¯´ï¼æå¦ä¸æ¾èç好å¤ï¼
(1)éåå¤ä¸ªç¸åç¨åºä»£ç ç线ç¨å»å¤çåä¸èµæºçæ åµï¼æèæCPUï¼çº¿ç¨ï¼åç¨åºç代ç ï¼æ°æ®ææçå离ï¼è¾å¥½å°ä½ç°äºé¢å对象ç设计ææ³ã
(2)å¯ä»¥é¿å ç±äºJavaçå继æ¿ç¹æ§å¸¦æ¥çå±éãæ们ç»å¸¸ç¢°å°è¿æ ·ä¸ç§æ åµï¼å³å½æ们è¦å°å·²ç»ç»§æ¿äºæä¸ä¸ªç±»çåç±»æ¾å ¥å¤çº¿ç¨ä¸ï¼ç±äºä¸ä¸ªç±»ä¸è½åæ¶æ两个ç¶ç±»ï¼æ以ä¸è½ç¨ç»§æ¿Threadç±»çæ¹å¼ï¼é£ä¹ï¼è¿ä¸ªç±»å°±åªè½éç¨å®ç°Runnableæ¥å£çæ¹å¼äºã
(3)æå©äºç¨åºçå¥å£®æ§ï¼ä»£ç è½å¤è¢«å¤ä¸ªçº¿ç¨å ±äº«ï¼ä»£ç ä¸æ°æ®æ¯ç¬ç«çãå½å¤ä¸ªçº¿ç¨çæ§è¡ä»£ç æ¥èªåä¸ä¸ªç±»çå®ä¾æ¶ï¼å³ç§°å®ä»¬å ±äº«ç¸åç代ç ãå¤ä¸ªçº¿ç¨æä½ç¸åçæ°æ®ï¼ä¸å®ä»¬ç代ç æ å ³ãå½å ±äº«è®¿é®ç¸åç对象æ¯ï¼å³å®ä»¬å ±äº«ç¸åçæ°æ®ãå½çº¿ç¨è¢«æé æ¶ï¼éè¦ç代ç åæ°æ®éè¿ä¸ä¸ªå¯¹è±¡ä½ä¸ºæé å½æ°å®åä¼ éè¿å»ï¼è¿ä¸ªå¯¹è±¡å°±æ¯ä¸ä¸ªå®ç°äºRunnableæ¥å£çç±»çå®ä¾ã Javaä¸RunnableåThreadçåºå«æ´è¯¦ç»çèµæåèï¼/course/course_id-.html