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()加入到当前线程中

首先解释一下<mark>主线程</mark>的概念
所有进程,至少会有一个线程即主线程,即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();
    }
}

我们运行,会发现直接运行结束,因为进程里,所有的线程都是守护线程,所以结束当前进程。