线程五大状态

  • 创建状态
  • 就绪状态
  • 阻塞状态
  • 运行状态
  • 死亡状态

状态结构导图

线程方法

方法说明
setPriority(int newPriority)更改线程的优先级
static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程体休眠
void join()等待该线程终止
static void yield()暂停当前正在执行的线程对象,并执行其他线程
void interrupt()中断线程(此方法尽量少用)
boolean isAlive()测试线程是否处于活动状态

线程停止

建议:

  1. 建议线程正常停止,即利用次数,不建议死循环。
  2. 建议使用标志位,即设置一个标志位。
  3. 不建议使用stop或者destroy等过时以及JDK不建议使用的方法。

代码

//线程停止
public class Thread05 implements Runnable{
    //设置标志位
    private boolean  flag = true;
    //线程运行
    @Override
    public void run() {
        int count = 0;
        while (flag){
            System.out.println("Run......" + count++);
        }

    }

    //创建一个class,改变标志位
    public void ThreadStop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        //开启线程
        Thread05 thread05 = new Thread05();
        new Thread(thread05).start();
        //制约线程停止的条件
        for (int i = 0; i < 100; i++) {
            System.out.println("main......" + i);
            if (i == 50){
                thread05.ThreadStop();
                System.out.println("线程停止");
            }
        }
    }
}

注意:这里只是run()方法的线程停止,而主线程并未停止,而是一直运行到循环结束。

图示

线程休眠

sleep作用:

  • sleep(时间)指定当前线程阻塞的毫秒数。
  • sleep存在异常interruptedException。
  • sleep时间到达后线程进入就绪状态。
  • sleep可以模拟网络延时,倒计时等。
  • 每一个对象都有一个锁,sleep不会释放锁。(后面回过头在来理解。)

模拟网络延时

代码

模拟抢票

public class Thread06 implements Runnable{
    private int piao = 1;
    @Override
    public void run() {
        while (true){
            if (piao > 10){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了第" + piao++ + "张票");
        }
    }

    public static void main(String[] args) {
        Thread06 thread06 = new Thread06();
        new Thread(thread06,"小明").start();
        new Thread(thread06,"小红").start();
        new Thread(thread06,"黄牛党").start();
    }
}
图示

注意:模拟延时会放大问题的发生性

模拟倒计时

代码
public class Thread07 implements Runnable{
    @Override
    public void run() {
        int math = 10;
        while (true){
            if (math <= 0){
                break;
            }
            System.out.println(math--);

        //模拟倒计时,1000为一秒
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        }
    }

    public static void main(String[] args) {
        Thread07 thread07 = new Thread07();
        new Thread(thread07).start();
    }
}
拓展(获取系统当前时间)
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;

//获取当前时间
public class Thread070 implements Runnable{
    @Override
    public void run() {
        //打印当前系统时间
        Date starTime = new Date(System.currentTimeMillis()); //获取当前时间
        while (true){
            try {
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(starTime));
                Thread.sleep(1000);
                starTime = new Date(System.currentTimeMillis()); //更新当前时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread070 thread070 = new Thread070();
        new Thread(thread070).start();
    }
}

线程礼让

礼让yield:
  • 礼让线程,让当前正在执行的线程暂停,但不阻塞。
  • 讲线程从运行状态转为就绪状态。
  • 让CPU重新调度,礼让不一定成功!看CPU的心情。(完全看CPU的心情)
代码
public class Thread08 {
    public static void main(String[] args) {
        Yield yield = new Yield();
        new Thread(yield,"小明").start();
        new Thread(yield,"小红").start();
    }
}


class Yield implements Runnable{
    @Override
    public void run() {
        System.out.println("我想对很礼貌" + Thread.currentThread().getName());
        Thread.yield(); //线程礼让
        System.out.println("最后我又不想和你交流" + Thread.currentThread().getName());
    }
}
图示

注意:即使不加Thread.yield();也会礼让,只是添加后会使得礼让更加的频繁。

强制执行

强制Join:
  • Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。
  • 相当于排队打饭中的插队。
代码
public class Thread09 {
    public static void main(String[] args) throws InterruptedException {
        Join join = new Join();
        Thread thread = new Thread(join);
        thread.start();

        for (int i = 1; i <= 2000; i++) {
            if (i == 200){
                thread.join();
            }
            System.out.println("普通用户" + i + "在排队");
        }
    }
}
class Join implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 20; i++) {
            if (i % 2 == 0){
                //此处为防止子线程运行过快在200号之前就跑完的情况
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("VIP用户" + i + "在排队");
        }
    }
}
图示

图二的原因解释:强制执行并不是阻止子线程在200号打饭之前停止运行,而是假如20位VIP客户没有在200号之前排完队打饭,这时候VIP的作用显示出来,让剩余的VIP客户直接排在199号,直到VIP客户排完打饭后,普通用户在接着200号排队打饭

守护线程

守护概述:

  • 线程分为用户线程和守护线程。
  • 虚拟机必须确保用户线程执行完毕。
  • 虚拟机不用等待守护线程执行完毕。
  • 如,后台记录操作日志,监控内存,垃圾回收。

thread.thread.setDaemon(),一般情况下默认为false,表示为用户线程,正常的线程都是用户线程。

代码

public class Thread12 {
    public static void main(String[] args) {
        God god = new God();
        Youself you = new Youself();

        Thread thread = new Thread(god);
        thread.setDaemon(true);

        thread.start();//开始上帝保佑

        new Thread(you).start();//开启你的人生之路

    }
}

//上帝默默保佑着你
class God implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("God is watching over you");
        }
    }
}

//你还在世上
class Youself implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你还活着");
        }
        System.out.println("======The end of life======");
    }
}

图示

image-20210308182943950

观测线程状态

  • Thread.State()

    • NEW

      尚未启动的线程处于此状态。

    • RUNNABLE

      在Java虚拟机中执行的线程处于此状态。

    • BLOCKED

      被阻塞等待监视器锁定的线程属于此状态。

    • WATTING

      正在等待另一个线程执行特定动作的线程处于此状态。

    • TIMED_WATTING

      正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。

    • TERMINATED

      已退出的线程处于此状态。

    一个线程可以在给定时间点处于一个状态 。这些状态是不反映任何操作系统线程状态的虚拟机状态。

    代码

    public class State {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(()->{  //lamda表达式
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Run......");
                }
            });
    
            //观测状态
            Thread.State state = thread.getState();  //NEW
            System.out.println(state);
    
            //启动后
            thread.start();
            state = thread.getState();
            System.out.println(state);  //Run
    
            while (state != Thread.State.TERMINATED) {
                Thread.sleep(100);
                state = thread.getState();
                System.out.println(state);  //阻塞sleep,TIMED_WAITING
            }
        }
    }
    

    图示

线程运行结束后便死亡,不能重复开始线程

Q.E.D.