歡迎您光臨本站 註冊首頁

java線程的若干技巧

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0
java中有幾種方法可以實現一個線程?用什麼關鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?
java5以前,有如下兩種:
第一種:
new Thread(){}.start();這表示調用Thread子類對象的run方法,new Thread(){}表示一個Thread的匿名子類的實例對象,子類加上run方法后的代碼如下:
new Thread(){
public void run(){
}
}.start();
第二種:
new Thread(new Runnable(){}).start();這表示調用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個Runnable的匿名子類的實例對象,runnable的子類加上run方法后的代碼如下:
new Thread(new Runnable(){
public void run(){
}
}
).start();
從java5開始,還有如下一些線程池創建多線程的方式:
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i )
{
pool.execute(new Runable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){public void run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){public void run(){}});
有兩種實現方法,分別使用new Thread()和new Thread(runnable)形式,第一種直接調用thread的run方法,所以,我們往往使用Thread子類,即new SubThread().第二種調用runnable的run方法.
有兩種實現方法,分別是繼承Thread類與實現Runnable介面
用synchronized關鍵字修飾同步方法
反對使用stop(),是它不安全.它會解除由線程獲取的所有鎖定,如果對象處於一種不連貫狀態,那麼其他線程能在那種狀態下檢查和修改它們.結果很難檢查出真正的問題所在.suspend()方法容易發生死鎖.調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定.此時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行.對任何線程來說,如果它們想恢複目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖.所以不應該使用suspend(),而應在自己的Thread類中置入一個標誌,指出線程應該活動還是掛起.若標誌指出線程應該掛起,便用wait()命其進入等待狀態.若標誌指出線程應當恢復,則用一個notify()重新啟動線程.
sleep() 和 wait() 有什麼區別?
(網上的答案:sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控狀態依然保持,到時後會自動恢復.調用sleep不會釋放對象鎖. wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態.)


sleep就是正在執行的線程主動讓出cpu,cpu去執行其他線程,在sleep指定的時間過後,cpu才會回到這個線程上繼續往下執行,如果當前線程進入了同步鎖,sleep方法並不會釋放鎖,即使當前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無法得到執行.wait是指在一個已經進入了同步鎖的線程內,讓自己暫時讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖並運行,只有其他線程調用了notify方法(notify並不釋放鎖,只是告訴調用過wait方法的線程可以去參與獲得鎖的競爭了,但不是馬上得到鎖,鎖還在別人手裡,別人還沒釋放.如果notify方法後面的代碼還有很多,需要這些代碼執行完后才會釋放鎖,可以在notfiy方法后增加一個等待和一些代碼,看看效果),調用wait方法的線程就會解除wait狀態和程序可以再次得到鎖後繼續向下運行.對於wait的講解一定要配合例子代碼來說明,才顯得自己真明白.
package com.huawei.interview;
public class MultiThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(new Thread1()).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
//由於這裡的Thread1和下面的Thread2內部run方法要用同一對象作為監視器,我們這裡不能用this,在Thread2裡面的this和這個Thread1的this不是同一個對象.我們用MultiThread.class這個位元組碼對象,當前虛擬機里引用這個變數時,指向的都是同一個對象.
synchronized (MultiThread.class) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting");
try {
//釋放鎖有兩種方式,第一種方式是程序自然離開監視器的範圍,也就是離開了synchronized關鍵字管轄的代碼範圍,另一種方式就是在synchronized關鍵字管轄的代碼內部調用監視器對象的wait方法.這裡,使用wait方法釋放鎖.
MultiThread.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread1 is going on...");
System.out.println("thread1 is being over!");
}
}
}
private static class Thread2 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (MultiThread.class) {
System.out.println("enter thread2...");


System.out.println("thread2 notify other thread can release wait status..");
//由於notify方法並不釋放鎖, 即使thread2調用下面的sleep方法休息了10毫秒,但thread1仍然不會執行,thread2沒有釋放鎖,所以Thread1無法得不到鎖.
MultiThread.class.notify();
System.out.println("thread2 is sleeping ten millisecond...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread2 is going on...");
System.out.println("thread2 is being over!");
}
}
}
}


[火星人 ] java線程的若干技巧已經有346次圍觀

http://coctec.com/docs/java/show-post-59975.html