多線程 常見的線程方法

sleep()線程暫停

Thread.sleep(1000); 表示當前線程暫停1000毫秒 ,其他線程不受影響
Thread.sleep(1000); 會拋出InterruptedException 中斷異常,因爲當前線程sleep的時候,有可能被停止,這時就會拋出 InterruptedException

package multiplethread;
public class TestThread {
    public static void main(String[] args) {
        Thread t1= new Thread(){
            public void run(){
                int seconds =0;
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.printf("已經玩了LOL %d 秒%n", seconds++);
                }              
            }
        };
        t1.start();   
    }  
}

join()加入到當前線程中

首先解釋一下主線程的概念
所有進程,至少會有一個線程即主線程,即main方法開始執行,就會有一個看不見的主線程存在。
在這裏插入圖片描述
在執行t.join,即表明在主線程中加入該線程。

主線程會等待該線程結束完畢, 纔會往下運行。

package charactor;
import java.io.Serializable;
public class Hero{
    public String name;
    public float hp; 
    public int damage;
    public void attackHero(Hero h) {
        try {
            //爲了表示攻擊需要時間,每次攻擊暫停1000毫秒
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        h.hp-=damage;
        System.out.format("%s 正在攻擊 %s, %s的血變成了 %.0f%n",name,h.name,h.name,h.hp);
        if(h.isDead())
            System.out.println(h.name +"死了!");
    }
    public boolean isDead() {
        return 0>=hp?true:false;
    }
}

package multiplethread;
import charactor.Hero;
public class TestThread {
    public static void main(String[] args) { 
        final Hero gareen = new Hero();
        gareen.name = "蓋倫";
        gareen.hp = 616;
        gareen.damage = 50;
  
        final Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 300;
        teemo.damage = 30;
          
        final Hero bh = new Hero();
        bh.name = "賞金獵人";
        bh.hp = 500;
        bh.damage = 65;
          
        final Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 455;
        leesin.damage = 80;
          
        Thread t1= new Thread(){
            public void run(){
                while(!teemo.isDead()){
                    gareen.attackHero(teemo);
                }              
            }
        };
          
        t1.start();
 
        //代碼執行到這裏,一直是main線程在運行
        try {
            //t1線程加入到main線程中來,只有t1線程運行結束,纔會繼續往下走
            t1.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        Thread t2= new Thread(){
            public void run(){
                while(!leesin.isDead()){
                    bh.attackHero(leesin);
                }              
            }
        };
        //會觀察到蓋倫把提莫殺掉後,才運行t2線程
        t2.start();
    } 
}

因爲使用join將t1加入了主線程,主線程會最先執行,所以運行結果是先將線程t1執行結束,再執行t2.
在這裏插入圖片描述

setPriority()設置線程優先級

當線程處於競爭關係的時候,優先級高的線程會有更大的機率獲得CPU資源
爲了演示該效果,要把暫停時間去掉,多條線程各自會盡力去佔有CPU資源
同時把英雄的血量增加100倍,攻擊減低到1,纔有足夠的時間觀察到優先級的演示
線程優先級的範圍在1-10
如圖可見,線程1的優先級是MAX_PRIORITY,所以它爭取到了更多的CPU資源執行代碼

package charactor;
import java.io.Serializable;
public class Hero{
    public String name;
    public float hp;
    public int damage;
    public void attackHero(Hero h) {
        h.hp-=damage;
        System.out.format("%s 正在攻擊 %s, %s的血變成了 %.0f%n",name,h.name,h.name,h.hp);
        if(h.isDead())
            System.out.println(h.name +"死了!");
    }
    public boolean isDead() {
        return 0>=hp?true:false;
    }
  
}
package multiplethread;
import charactor.Hero;
public class TestThread {
    public static void main(String[] args) {
        final Hero gareen = new Hero();
        gareen.name = "蓋倫";
        gareen.hp = 6160;
        gareen.damage = 1;
  
        final Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 3000;
        teemo.damage = 1;
          
        final Hero bh = new Hero();
        bh.name = "賞金獵人";
        bh.hp = 5000;
        bh.damage = 1;
          
        final Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 4505;
        leesin.damage = 1;
          
        Thread t1= new Thread(){
            public void run(){
                while(!teemo.isDead()){
                    gareen.attackHero(teemo);
                }              
            }
        };
        Thread t2= new Thread(){
            public void run(){
                while(!leesin.isDead()){
                    bh.attackHero(leesin);
                }              
            }
        };
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }
}

在這裏插入圖片描述

yield()臨時暫停

yield中文翻譯投降,起作用也差不多這個意思,當前線程,臨時暫停,使得其他線程可以有更多的機會佔用CPU資源,就像兩個人搶喫的,甲,乙都想喫多點,打起來了,乙輸了,就投降了,甲就喫的多,獲取更多資源,但是不可能甲全吃了,乙還有不服的時候呢,就會加強鍛鍊,鍛鍊好了,就去再跟甲打架,來獲取資源。這裏跟sleep有明顯的不同,sleep有固定的暫停時間,但是 yield只是臨時認慫,沒有固定時間。

package multiplethread;
import charactor.Hero;
public class TestThread {
    public static void main(String[] args) {
        final Hero gareen = new Hero();
        gareen.name = "蓋倫";
        gareen.hp = 61600;
        gareen.damage = 1;
  
        final Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 30000;
        teemo.damage = 1;
          
        final Hero bh = new Hero();
        bh.name = "賞金獵人";
        bh.hp = 50000;
        bh.damage = 1;
          
        final Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 45050;
        leesin.damage = 1;
          
        Thread t1= new Thread(){
            public void run(){
 
                while(!teemo.isDead()){
                    gareen.attackHero(teemo);
                }              
            }
        };
        Thread t2= new Thread(){
            public void run(){
                while(!leesin.isDead()){
                    //臨時暫停,使得t1可以佔用CPU資源
                    Thread.yield();
                     
                    bh.attackHero(leesin);
                }              
            }
        };
        t1.setPriority(5);
        t2.setPriority(5);
        t1.start();
        t2.start();
    } 
}

在這裏插入圖片描述

setDaemon()守護線程

守護線程的概念是: 當一個進程裏,所有的線程都是守護線程的時候,結束當前進程。
舉個實際的例子,就像我們打開一個LOL,我們打遊戲的時候,後臺會記錄我們這一局輸出多少,參團率多少等等,當本局遊戲結束了,我們退出,返回主界面,那些記錄我們參團率,輸出的進行就相應的結束了。那些記錄數據的線程就是守護進程,所以我們可以想一下,是不是當所有的進程都是這種記錄的守護進程時,這個程序就沒有運行的必要了,所以就結束了當前的進程。
守護線程通常會被用來做日誌,性能統計等工作。

package multiplethread;
public class TestThread {
    public static void main(String[] args) {
        Thread t1= new Thread(){
            public void run(){
                int seconds =0;
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.printf("已經玩了LOL %d 秒%n", seconds++);
                }              
            }
        };
        t1.setDaemon(true);
        t1.start();
    }
}

我們運行,會發現直接運行結束,因爲進程裏,所有的線程都是守護線程,所以結束當前進程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章