线程的五个状态

image.png
创建状态:Thread t = new Thread();
就绪状态:调用start方法
运行状态:被cpu调度执行
阻塞状态:调用sleep、wait或同步锁定时,进入阻塞状态
死亡状态:线程中断或者结束,一旦死亡就不再启动

停止线程

jdk自带stop()和destroy()来停止一个线程,但是官方已经不推荐使用了,这里推荐让线程自己停下来,但也不建议使用死循环,建议使用一个标志位作为终止变量,当flag==false时,线程终止运行:

  1. package com.wjh.service;
  2. /**
  3. * @author wjh
  4. * @date 2021/7/19 16:09
  5. * @Package com.wjh.service
  6. */
  7. public class MyThread implements Runnable {
  8. private boolean flag = true;
  9. @Override
  10. public void run() {
  11. while (flag) {
  12. System.out.println("子线程执行中~~~");
  13. }
  14. }
  15. public void stop() {
  16. this.flag = false;
  17. }
  18. public static void main(String[] args) {
  19. MyThread myThread = new MyThread();
  20. new Thread(myThread).start();
  21. for (int i = 0; i < 10; i++) {
  22. System.out.println("主进程执行中,i的值:" + i);
  23. if (i == 9) {
  24. myThread.stop();
  25. System.out.println("子进程结束运行!");
  26. }
  27. }
  28. }
  29. }

线程休眠(sleep)

使线程休眠的方法是sleep(),参数类型是long,单位是毫秒,它需要捕捉InterruptedException异常。使用该方法后线程进入就绪状态,不会直接进入执行状态,可以用于模拟网络延时,倒计时等。每个对象都有一个锁,sleep不释放锁。

  1. try {
  2. Thread.sleep(1000);
  3. } catch (InterruptedException e) {
  4. e.printStackTrace();
  5. }

线程礼让(yield)

线程礼让是暂停执行当前线程,转而执行其他线程,但具体执行那个线程,由cpu调度决定(可能依然执行此线程,即礼让不一定成功)。

  1. package com.wjh.service;
  2. /**
  3. * @author wjh
  4. * @date 2021/7/19 16:09
  5. * @Package com.wjh.service
  6. */
  7. public class MyThread implements Runnable {
  8. @Override
  9. public void run() {
  10. System.out.println(Thread.currentThread().getName() + "线程开始执行");
  11. Thread.yield();//礼让
  12. System.out.println(Thread.currentThread().getName() + "线程停止执行");
  13. }
  14. public static void main(String[] args) {
  15. MyThread myThread = new MyThread();
  16. new Thread(myThread,"a线程").start();
  17. new Thread(myThread,"b线程").start();
  18. }
  19. }

礼让成功:
image.png
礼让失败:
image.png

线程插队(join)

join的意思是:cpu停止执行其它线程,让调用join方法的线程优先执行完毕才去执行其它的线程。

package com.wjh.service;

/**
 * @author wjh
 * @date 2021/7/19 16:09
 * @Package com.wjh.service
 */
public class MyThread implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("子线程执行中---->" + i);
        }
    }

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread = new Thread(myThread);
        thread.start();

        for (int i = 0; i < 30; i++) {
            if (i == 15) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println("main线程执行中---->" + i);
        }

    }
}

运行结果:
image.png

观察线程的状态

线程的状态 - 图5

Thread.State state = thread.getState();
System.out.println(state);

线程的优先级

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行,线程的优先级用数字1~10(int类型,超过最大值或小于最小值会抛出异常)来表示,我们可以使用setPriority(int x)来设置线程的优先级,使用getPriority()来获取线程的优先级。理论上线程的优先级越高越先启动,即使它start的晚,但这也不是绝对的事。
Thread.MIN PRIORITY= 1;
Thread.MAX PRIORITY = 10;
Thread.NORM
PRIORITY= 5;
其中,main线程默认是5,如果创建的线程没有指定优先级也是5。

守护线程

线程分为用户线程和守护线程,虚拟机必须确保用户线程执行完毕,而不用等待守护线程执行完毕,守护线程一般用于:后台记录操作日志,监控内存,垃圾回收……
我们可以使用Thread.setDaemon(true)设置为守护线程,创建的线程默认是用户线程。

package com.wjh.service;

/**
 * @author wjh
 * @date 2021/7/19 16:09
 * @Package com.wjh.service
 */
public class MyThread {

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

        Thread godThread = new Thread(god);
        godThread.setDaemon(true);
        godThread.start();

        Thread youThread = new Thread(you);
        youThread.start();
    }

}

class God implements Runnable {

    @Override
    public void run() {
        //上帝永生,无限循环
        while (true) {
            System.out.println("上帝守护这你");
        }
    }
}

class You implements Runnable {

    @Override
    public void run() {
        //人生有限,100年后撒手人寰
        for (int i = 0; i < 100; i++) {
            System.out.println("happy everyday");
        }
        System.out.println("goodbye world");

    }
}