建立執行緒的兩種方式:
1.繼承Thread,重寫run方法,使用start()使用執行緒
2.將Runnable作為Thread的構造引數
複製程式碼
public class ThreadCreate {
public static void main(String[] args) {
System.out.println("主執行緒ID:" + Thread.currentThread().getId());
/**
* 第一種建立執行緒的方式
*/
Thread firstMethod2CreateThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子執行緒ID:" + Thread.currentThread().getId());
}
});
firstMethod2CreateThread.start();
/**
* 第二種建立執行緒的方式
*/
class SecondMethod2CreateThread extends Thread {
@Override
public void run() {
System.out.println("子執行緒ID:" + Thread.currentThread().getId());
}
}
SecondMethod2CreateThread secondMethod2CreateThread = new SecondMethod2CreateThread();
secondMethod2CreateThread.start();
}
}
複製程式碼
Thread類詳解:
JAVA中多執行緒的核心是Thread,Thread翻譯為執行緒,執行緒有以下幾種狀態,接下來我會按照Thread類中的方法來逐一講解。
複製程式碼
1.Thread t = new Thread()僅僅只是建立了執行緒,並沒有為執行緒分配任何資源
2.start()方法用來啟動執行緒,為相應地執行緒分配資源,分配到資源才能參與到競爭CPU的過程中
run():當start()啟動一個執行緒後,執行緒一直等待直到獲得了CPU執行時間,就進入run方法體
3.sleep()讓執行緒休眠,主動讓出CPU,但是不會釋放鎖,休眠時間滿後,不一定立即得到執行,還需要重新參與競爭排隊
public class ThreadSleep {
private int i = 0;
public Object lock = new Object();
public static void main(String[] args) {
ThreadSleep mh = new ThreadSleep();
ThreadTest tt = mh.new ThreadTest();
ThreadTest tt2 = mh.new ThreadTest();
tt.start();
tt2.start();
}
class ThreadTest extends Thread {
@Override
public void run() {
//使用的鎖為Object lock = new Object(); 而不是方法所在的類的內建monitor
synchronized (lock) {
i++;
System.out.println("i:" + i);
try {
System.out.println("執行緒i:" + Thread.currentThread().getId() + "睡眠開始");
long startTime = System.currentTimeMillis();
Thread.currentThread().sleep(1000);
long endTime = System.currentTimeMillis();
System.out.println("執行緒i:" + Thread.currentThread().getId() + "睡眠時間:" + (endTime - startTime));
} catch (Exception e) {
} finally {
System.out.println("執行緒i:" + Thread.currentThread().getId() + "睡眠結束");
}
i++;
System.out.println("i:" + i);
}
}
}
}
複製程式碼
輸出:
i:1
執行緒i:9睡眠開始
執行緒i:9睡眠時間:1005
執行緒i:9睡眠結束
i:2
i:3
執行緒i:10睡眠開始
執行緒i:10睡眠時間:1004
執行緒i:10睡眠結束
i:4
複製程式碼
4.yield()使執行緒讓出CPU去執行相同優先順序的其他程式,但是不會釋放鎖,(內部還是sleep)執行yield()之後該執行緒直接進入就緒狀態再次參與競爭,生產中很少使用。
5.A執行緒的run()中呼叫了B執行緒的join(),則A執行緒等待B執行緒執行完之後,再繼續執行,實際上呼叫了Object類中的wait()方法,會釋放鎖
public class ThreadJoin {
public static void main(String[] args) throws IOException {
System.out.println("進入執行緒"+Thread.currentThread().getName());
ThreadJoin test = new ThreadJoin();
MyThread thread1 = test.new MyThread();
thread1.start();
try {
System.out.println("執行緒"+Thread.currentThread().getName()+"等待");
thread1.join();
System.out.println("執行緒"+Thread.currentThread().getName()+"繼續執行");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("進入執行緒"+Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("執行緒"+Thread.currentThread().getName()+"執行完畢");
}
}
}
複製程式碼
輸出:
進入執行緒main
執行緒main等待
進入執行緒Thread-0
執行緒Thread-0執行完畢
執行緒main繼續執行
複製程式碼
6.interrupt()使得處於阻塞狀態的執行緒丟擲一個異常,也就是說,它可以中斷並且只能中斷一個處於阻塞狀態的執行緒
public class ThreadInterrput {
public static void main(String[] args) {
ThreadInterrput mh = new ThreadInterrput();
ThreadTest tt = mh.new ThreadTest();
tt.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
}
tt.interrupt();
}
class ThreadTest extends Thread {
@Override
public void run() {
try {
System.out.println("子執行緒睡眠開始");
Thread.currentThread().sleep(10000);
System.out.println("子執行緒睡眠結束");
} catch (InterruptedException e) {
System.out.println("子執行緒獲取到中斷");
}
System.out.println("run執行完畢");
}
}
}
複製程式碼
輸出:
子執行緒睡眠開始
子執行緒獲取到中斷
run執行完畢
複製程式碼
7.開發中一般不使用interrupt()而在類中增加isStop屬性來標誌是否結束while迴圈
class MyThread extends Thread{
private volatile boolean isStop = false;
@Override
public void run() {
int i = 0;
while(!isStop){
i++;
}
}
public void setStop(boolean stop){
this.isStop = stop;
}
}
複製程式碼
這樣一來便可線上程外通過呼叫setStop方法來終止while迴圈。