四、线程状态

一、线程状态

操作系统中,线程被视为轻量级的进程,因此操作系统的线程状态与操作系统的进程状态是一致的

1. 线程五大状态

  • 创建状态

    Thread t = new Thread() 线程对象一旦创建就进入到了新生状态

  • 就绪状态

    当调用start() 方法,线程会进入就绪状态,但不意味着立即执行

  • 运行状态

    进入运行状态,线程才会真正去执行线程体的代码

  • 阻塞状态

    当调用sleep()wait()或同步锁定时,线程进入阻塞状态,代码不会继续执行。等待阻塞事件解除后,重新进入就绪状态,等待CPU调度执行

  • 死亡状态

    线程中断或结束,一旦进入死亡状态就不能再启动

线程状态

2. 线程中的一些方法

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

二、操控线程

1. 停止线程

1.1 要点

  • 不推荐使用 JDK 提供的stop()destory() 等方法
  • 推荐等待线程自己停止,例如使用for循环限制次数,不建议死循环
  • 建议使用一个标志位终止变量,例如当flag == false时,终止线程运行

1.2 示例

public class TestStop implements Runnable {
	// 1. 定义标识
    private static boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run......Thread " + i++);
            if (i >= 30) {
                TestStop.stop();
                System.out.println("该线程已停止");
            }
        }
    }
	// 2. 对外提供方法改变标识
    public static void stop() {
        flag = false;
    }

    public static void main(String[] args) {
        TestStop t = new TestStop();
        new Thread(t).start();

        for (int i = 0; i < 100; i++) {
            System.out.println("main线程 " + i);
        }
    }
}

2. 线程休眠

2.1 要点

  • sleep()中的参数指定当前线程阻塞的毫秒数
  • sleep()方法存在异常InterruptedException
  • sleep()时间达到后线程进入就绪状态
  • sleep()可以模拟网络延时、倒计时等
  • 每个对象都有一个锁,sleep()不会释放锁

2.2 示例

例1. 模拟网络延迟,放大可能发生的问题的出现几率
public class TestSleep implements Runnable {
    private int ticketNum = 10;

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNum-- + "张票");
        }
    }

    public static void main(String[] args) {
        TestSleep t = new TestSleep();
         new Thread(t, "小明").start();
         new Thread(t, "老师").start();
         new Thread(t, "黄牛党").start();
    }
}

例2. 模拟倒计时
public class TestSleep {
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while (true) {
            Thread.sleep(1000);
            System.out.println(num--);
            if (num <= 0) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3. 线程礼让

3.1 要点

  • 礼让线程,让当前正在执行的线程暂停
  • 将线程从运行状态转为就绪状态
  • 让 CPU 重新调度,礼让成功与否由 CPU 调度决定

3.2 示例

public class TestYield {
    public static void main(String[] args) {
        MyYield m = new MyYield();

        new Thread(m, "a").start();
        new Thread(m, "b").start();
    }
}

class MyYield implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }
}

4. 线程强制执行

4.1 要点

  • join合并线程,待此线程执行结束后,再执行其它线程。期间其它线程阻塞
  • 类似于现实生活中的插队

4.2 示例

public class TestJoin implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 200; i++) {
            System.out.println("插队线程 " + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin t = new TestJoin();
        Thread thread = new Thread(t);
        thread.start();

        for (int i = 0; i < 100; i++) {
            if (i == 50) {
                thread.join();
            }
            System.out.println("main方法线程 " + i);
        }
    }
}

三、观察线程状态

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("//////////");
        });

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

        // 观察启动后状态
        t.start();
        state = t.getState();
        System.out.println(state);

        // 线程执行期间重复监测
        while (state != Thread.State.TERMINATED) {
            Thread.sleep(100);
            state = t.getState();
            System.out.println(state);
        }
    }
}

四、扩展

Java线程的六个状态

  • NEW:新创建还未启动,指还未调用start()方法
  • RUNNABLE:可运行,此状态的线程可能正在 Java 虚拟机中运行,也可能正在等待 CPU 分配资源,即包含了传统操作系统线程状态中的readyrunnig两个状态
  • BLOCKED:被阻塞,该状态的下的线程正在等待锁释放以进入同步区
  • WAITING:等待,该状态下的线程需要被其他线程唤醒才会转为RUNNABLE状态
  • TIMED_WATING:计时等待,等待指定时间后会被唤醒
  • TERMINATED:终止状态,线程已执行完毕
posted @ 2021-08-02 17:17  冷火凉烟  阅读(87)  评论(0)    收藏  举报