一榆纽、 多線程與多進(jìn)程的區(qū)別:
最本質(zhì)的區(qū)別是每個進(jìn)程擁有自己的一整套變量,而線程則共享數(shù)據(jù)坑质。 共享變量使得線程之間的通信比進(jìn)程之
間的通信更有效痒留、更容易购披。同時芹敌,與進(jìn)程相比痊远,線程更加“輕量級”,創(chuàng)建氏捞、撤銷一個線程比啟動新繼承的開銷要
小得多碧聪。
二、Thread提供的主要方法
- Thread(Runnable r);
- void start();
- void run();
- Thread currentThread();
- static boolean interrupted();
- boolean isInterrupted();
- sleep(long s);
- void interrupt();
- void join();
- void join(long s);
- Thread.State getState();
三液茎、 調(diào)用時機(jī)與主要區(qū)別
①創(chuàng)建線程主要有兩種方式逞姿,一種是繼承Thread辞嗡,重寫run方法,另一種是實現(xiàn)Runnanble接口滞造,并作為Thread的一個參數(shù)续室。代碼示例如下:
//繼承Thread
class MyThread extends Thread{
@Override
public void run(){
System.out.println("hello my thread");
}
}
Thread thread = new Thread(new MyThread());
//實現(xiàn)Runnable接口
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("hello my runnable");
}
}
Thread thread = new Thread(new MyRunnable());
//也是實現(xiàn)Runnable接口,通常為了方便會使用這種方式
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(2000);
t1.interrupt();
}catch (InterruptedException e){
e.getMessage();
}
}
});
②啟動線程
thread.start();
注意:直接調(diào)用run方法只是在原來的線程執(zhí)行run方法與普通的方法并沒有區(qū)別谒养,而調(diào)用是start方法則會新創(chuàng)建一個線程挺狰,并在該新線程中執(zhí)行run方法。
③線程的中斷
雖然有強(qiáng)制中斷線程的stop方法蝴光,但是已經(jīng)被棄用∷剩現(xiàn)在一般是通過設(shè)置中斷標(biāo)志位的方式來實現(xiàn)線程中斷达址。即在線程中執(zhí)行重復(fù)操作時蔑祟,將線程的中斷標(biāo)志位作為執(zhí)行循環(huán)的條件之一。
a. 通過Thread.currentThread()獲取當(dāng)前線程沉唠。
b. 通過thread.isInterrupted()來判斷thread這個線程是否被中斷置位疆虚,true代表被請求中斷。
c. 通過Thread.interrupted()來判斷執(zhí)行這條語句的線程是否被中斷置位满葛,同時會清除該線程的中斷狀態(tài)径簿。
d. 通過Thread.sleep(s)來使得當(dāng)前線程進(jìn)入休眠狀態(tài)s毫秒(雖然中斷和休眠好像沒有什么聯(lián)系,后面會講)
先來個需求:如果我們有兩個線程t1和t2嘀韧,在t1中循環(huán)執(zhí)行某些操作篇亭,同時t2要能決定t1什么時候結(jié)束。代碼實現(xiàn):
Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
while(Thread.currentThread.isInterrupted() == false && more work to do){
//more work to do
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run(){
try{
t1.interrupt();
}catch(Exception e){
e.getMessage();
}
}
});
t1.start();
t2.start();
第一個挺簡單的锄贷,沒有什么陷阱译蒂,那再來一個,如果這個時候我們要求t1沒處理完一次操作要休眠一段時間呢谊却。
看起來好像很簡單柔昼,之前也被坑過,難道不是直接在t1的循環(huán)體內(nèi)添加Thread.sleep()并捕捉中斷異常嗎炎辨。正常邏輯是如此捕透,可是sleep方法很奇特,如果中斷標(biāo)識被置位時執(zhí)行sleep方法碴萧,sleep不但不休眠而且會清除中斷標(biāo)識的狀態(tài)乙嘀,也就是中斷標(biāo)識位和sleep同時“失效”,也就是不按照我們所想的方式執(zhí)行破喻。那么正確的做法應(yīng)該是怎樣呢虎谢。代碼如下:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try{
while(true){
System.out.println(""+x++);
Thread.sleep(1000);//sleep和中斷標(biāo)志位的正確組合用法
}
}catch (InterruptedException e){
e.getMessage();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(2000);
t1.interrupt();
}catch (InterruptedException e){
e.getMessage();
}
}
});
t1.start();
t2.start();
四、小結(jié)
①Thread.currentThread().isinterrupted() 與 Thread.interrupted()的主要區(qū)別在于前者只做判斷低缩,而后者除了做判斷外還會清除線程的中斷狀態(tài)嘉冒。
②Thread.sleep()也會清除線程的中斷狀態(tài)曹货,并且會拋出InterruptedException的異常,從而使得中斷狀態(tài)取消并且不會進(jìn)入休眠狀態(tài)讳推。