1中断1。1interrupt 将线程的状态设置为中断,并不是直接停止非阻塞的运行中的线程。当线程进入该中断状态,且被Thread。join和Thread。sleep,Object。wait阻塞时该线程立即会抛出InterruptedException中断异常,从而提早终结阻塞状态。相反如果线程没有被阻塞,调用此方法时将不起作用,直到遇到wait,sleep,join等场景才会抛出InterruptedException中断异常停止运行中的线程。(如同设置一个前哨,如果遇到阻塞马上中断)使用方式Thread。currentThread()。interrupt();1。2interrupted源码publicstaticbooleaninterrupted(){测试某些线程是否已中断。中断状态是否根据传递的ClearInterrupted值重置。returncurrentThread()。isInterrupted(true);} 测试当前线程是否已中断。此方法将清除线程的中断状态。换言之,如果连续两次调用此方法,则第二次调用将返回false(除非当前线程在第一次调用清除其中断状态之后且在第二次呼叫检查它之前再次中断)。由于线程在中断时不活动而忽略的线程中断将由返回false的方法反映。1。3isInterrupted源码publicbooleanisInterrupted(){测试某些线程是否已中断。中断状态是否根据传递的ClearInterrupted值重置。returnisInterrupted(false);} 测试此线程是否已中断。线程的中断状态不受此方法的影响。由于线程在中断时不活动而忽略的线程中断将由返回false的方法反映。 1。4一段代码搞清interrupt、interrupted、isInterrupted的关系Testvoidinterrupted(){设置中断标志位Thread。currentThread()。interrupt();判断当前线程是否处于中断状态trueSystem。out。println(Thread。currentThread()。isInterrupted());清理中断标志位(返回是否清理成功)trueSystem。out。println(Thread。interrupted());再次清理falseSystem。out。println(Thread。interrupted());判断当前线程是否处于中断状态falseSystem。out。println(Thread。currentThread()。isInterrupted());}2sleep 阻塞当前正在运行的线程一段时间(该时间可以指定),它不会释放以获取到的锁。当阻塞时间到后会继续执行当前线程的后续逻辑。 在无锁状态下也可以直接调用此方法。实现线程的阻塞。每隔1秒打印一次时间Testvoidsleep()throwsInterruptedException{for(inti0;i10;i){DateFormatformatternewSimpleDateFormat(yyyyMMddHH:mm:ss);DatedatenewDate();Stringformatformatter。format(date);System。out。println(format);阻塞线程1sTimeUnit。SECONDS。sleep(1);}}3wait wait会阻塞当前线程,并且不会释放当前持有的锁。它与sleep不同的是,该方法必须通过锁对象来调用,不可无锁调用。wait()与wait(longtimeout)的区别在于无参方法必须通过notify()或notifyAll()来唤醒当前等待线程,而有参方法可以等待指定的时间后自动唤醒等待线程去争夺锁。TestpublicvoidtestWait(){对象finalBigDecimallocknewBigDecimal(10);ThreadthreadAnewThread((){synchronized(lock){System。out。println(我被线程A正在执行);try{该线程会放弃对象锁,该线程会被挂起lock。wait();}catch(InterruptedExceptione){thrownewRuntimeException(e);}System。out。println(如果我被打印,说明我被唤醒了);}});启动线程AthreadA。start();ThreadthreadBnewThread((){线程B争夺该对象的锁synchronized(lock){System。out。println(我被线程B正在执行);线程B会唤醒该对象的lock。notify();}});threadB。start();} 运行结果 例:模拟闭锁,主线程等待10个子线程执行完毕之后,主线程继续向下执行。且主线程最多等待10秒,若子线程在10秒内未完成将自动向下执行。模拟主线程执行逻辑publicclassMyWait{staticfinalObjectlocknewObject();publicstaticvoidmain(String〔〕args)throwsInterruptedException{System。out。println(进入主线程);计数器AtomicIntegercountnewAtomicInteger(0);启动10个子线程MyWaitSonmyWaitSonnewMyWaitSon(lock,count);for(inti1;i10;i){ThreadsonThreadnewThread(myWaitSon,soni);sonThread。start();}主线程挂起,且最多等待10ssynchronized(lock){lock。wait(10000L);System。out。println(主线程继续启动);}}}模拟子线程执行逻辑publicclassMyWaitSonimplementsRunnable{finalObjectlock;finalAtomicIntegercount;publicMyWaitSon(Objectlock,AtomicIntegercount){this。locklock;this。countcount;}Overridepublicvoidrun(){System。out。println(子线程启动了);synchronized(lock){System。out。println(当前线程为:Thread。currentThread()。getName(),count:count。incrementAndGet());通过计数器到达10个后唤醒主线程if(count。get()10){lock。notify();System。out。println(子线程唤醒主线程);}}}}进入主线程子线程启动了子线程启动了当前线程为:son1,count:1子线程启动了当前线程为:son2,count:2子线程启动了当前线程为:son3,count:3子线程启动了当前线程为:son4,count:4子线程启动了当前线程为:son5,count:5当前线程为:son6,count:6子线程启动了当前线程为:son7,count:7子线程启动了当前线程为:son8,count:8子线程启动了当前线程为:son9,count:9子线程启动了当前线程为:son10,count:10子线程唤醒主线程主线程继续启动4join 在多线程环境下,需要等待某一个线程执行完毕后才能继续向下执行逻辑,那么这种场景就可以使用join。 为了更加形象的说明,我们看图说话,如上图所示有三个线程,执行完毕的时间分别是5s、3s、10s。 当运行到第3s时,Thread2执行完毕,Thread1、3正在执行。 当运行到第5s时,Thread1执行完毕,Thread2等待了2s,Thread3正在执行。 当运行到第10s时,Thread3执行完毕,Thread1等待了5s,Thread2等待了7s。 当主线程从第10s之后再开始执行后续逻辑。那么这种场景就适合join来实现。 示例代码如下publicstaticvoidmain(String〔〕args)throwsInterruptedException{线程1Threadthread1newThread((){try{TimeUnit。SECONDS。sleep(5);System。out。println(线程1执行完毕);}catch(InterruptedExceptione){thrownewRuntimeException(e);}},thread1);线程2Threadthread2newThread((){try{TimeUnit。SECONDS。sleep(3);System。out。println(线程2执行完毕);}catch(InterruptedExceptione){thrownewRuntimeException(e);}},thread2);线程3Threadthread3newThread((){try{TimeUnit。SECONDS。sleep(10);System。out。println(线程3执行完毕);}catch(InterruptedExceptione){thrownewRuntimeException(e);}},thread3);主线程准备启动三个子线程thread1。start();thread2。start();thread3。start();主线程等待thread1、2、3执行结束thread1。join();thread2。join();thread3。join();主线程继续执行System。out。println(主线程执行结束);}线程2执行完毕线程1执行完毕线程3执行完毕主线程执行结束5yield yieId在实际生产中使用不多,它的作用是将当前线程CPU的执行权让出给其它线程。 例如当前线程正常循环打印010000的耗时要远远小于使用yieId方法打印的耗时publicstaticvoidmain(String〔〕args)throwsInterruptedException{ThreadthreadnewThread((){for(inti0;i10000;i){System。out。println(i);使用yield方法Thread。yield();}});longstartTimeSystem。currentTimeMillis();thread。start();thread。join();System。out。println(总耗时:(System。currentTimeMillis()startTime));} 未使用yield方法耗时70毫米左右,当使用yield方法后会达到100毫秒以上。 收藏吃灰去吧