Java筆記-多執行緒之執行緒控制
執行緒控制
我們已經知道了執行緒的排程,接下來我們就可以使用如下方法物件執行緒進行控制。
1.執行緒休眠
public static void sleep(long millis)
:讓當前執行緒處於暫停狀態,millis
引數毫秒值,即暫停時間。
程式碼演示如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
// 執行緒休眠 1000ms 即 1s
sleep(1000);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread("張飛");
MyThread t2 = new MyThread("關羽");
t1.start();
t2.start();
}
}
執行緒加入(執行緒強制執行)
public final void join()
:後面其他執行緒等待,當前執行緒執行完,後面其他執行緒再開始執行。
呼叫必須是在當前執行緒start以後,其他執行緒start之前。
程式碼演示如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
// 執行緒休眠 100ms
sleep(100);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t0 = new MyThread("劉備");
MyThread t1 = new MyThread("張飛");
MyThread t2 = new MyThread("關羽");
t0.start();
// 執行緒加入 執行緒強制執行
// 執行結果 劉備先買完,然後張飛關羽再多執行緒買
t0.join();
t1.start();
t2.start();
//如果這樣
/*
t1.start();
t0.start();
// 執行緒加入 執行緒強制執行
// 執行結果 劉備張飛多執行緒買,都買完之後,關羽再買
t0.join();
t2.start();
*/
}
}
3.執行緒禮讓
public static void yield()
:當前執行的執行緒,執行完畢後會禮讓後面的執行緒。也就是說最好的情況就是每個執行緒都交替執行,沒有連續多次執行同一個執行緒的情況發生。
但是由於執行緒執行具有隨機性,所以該方法並不能保證完全的交替執行,所以說效果並不好,用處較少。
演示程式碼如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
// 執行緒禮讓
Thread.yield();
for (int i = 0; i < 20; i++) {
try {
// 執行緒休眠 100ms
sleep(100);
System.out.println("我是---->" + getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("張飛");
MyThread t2 = new MyThread("關羽");
t1.start();
t2.start();
}
}
4.後臺執行緒(守護執行緒)
public final void setDaemon(boolean on)
:被守護執行緒如果執行結束,則守護執行緒直接終止,不繼續執行任何一行程式碼。
注意:守護執行緒要在聲明後,和start()
前宣告。否則報錯!
演示程式碼如下:
劉關張三兄弟,一起上陣殺敵。 目的:一旦劉備(主公)死了,關羽張飛就不再殺敵直接被俘虜了。
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName() + "--->已經到達戰場!");
// 執行緒禮讓
Thread.yield();
for (int i = 0; i < 20; i++) {
try {
// 執行緒休眠 100ms
sleep(100);
System.out.println(getName() + "開始對抗第 " + i + " 個敵人");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "--->戰死了!!!!");
}
}
2.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("張飛");
MyThread t2 = new MyThread("關羽");
// 設定後臺執行緒 守護執行緒
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
System.out.println("劉備----->到達戰場!!!!");
for (int i = 0; i < 10; i++) {
// 為了明顯讓主執行緒也休眠
Thread.sleep(100);
System.out.println("劉備開始對抗第 " + i + " 個敵人");
}
System.out.println("劉備戰死了!!!!");
}
}
5.中斷執行緒
例子:劉關張三兄弟都困了,劉備先挺不住睡覺了,關羽張飛看到就也睡覺了,但是劉備先醒了,看到他們兩個在睡覺,就把他們兩個叫醒了。
public final void stop()
:不推薦使用,此方法太血腥。直接中斷執行緒,後面程式碼不執行了。
例子中,就是劉備醒了後看到兩兄弟在睡覺,很生氣,叫人把他們弄死了。兩兄弟再也睡不醒了。
public void interrupt()
:不推薦使用,此方法太暴力,直接給當前執行緒丟擲了一個異常。
Interrupt()
方法會向子執行緒丟擲一個InterruptedException
異常,異常結束了子執行緒的休眠。
推薦使用的方法: 像停止一個高速旋轉的輪子一樣,慢慢停止旋轉。 程式碼:一般子執行緒裡面都是長迴圈或耗時操作,只要把長迴圈或耗時操作的狀態改為不再迴圈,則慢慢停止。 推薦使用:布林值,控制迴圈停止,溫和終止方式。
演示程式碼如下:
1.MyThread.java:
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName() + "--->開始睡覺!!!");
try {
for (int i = 0; i < 10 && Flag.FLAG; i++) {
// 執行緒休眠 1000ms
sleep(1000);
System.out.println(getName() + "--->正在睡覺--" + i);
}
} catch (InterruptedException e) {
System.out.println(getName() + "--->被一棒子打醒!");
}
System.out.println(getName() + "--->睡醒了!!!");
}
}
2.Flag.java:
public class Flag {
//僅僅用來判斷迴圈是否繼續
public static boolean FLAG = true;
}
3.Test.java:
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("張飛");
MyThread t2 = new MyThread("關羽");
t1.start();
t2.start();
System.out.println("劉備----->開始睡覺!!!!");
// 為了明顯讓主執行緒也休眠
Thread.sleep(3000);
System.out.println("劉備睡醒了!!!!");
// 使用boolean值控制迴圈停止,溫和
// 劉備睡醒後二人也能再睡短短的一會兒,然後被溫柔的叫醒
Flag.FLAG = false;
// 太暴力,一棒子打醒了二人
// t1.interrupt();
// t2.interrupt();
// 太血腥,直接弄死了二人,再也睡不醒了
// t1.stop();
// t2.stop();
}
}