JavaWeb笔记04:中断/线程状态转换

设置普通状态位让线程停止:

public class
普通状态位的方式通知停止 {
    private static boolean condition = true;

    static class 写作业 implements Runnable {
        @Override
        public void run() {
            while (condition) {
                try {
                    System.out.println("写第一份作业");
                    Thread.sleep(3 * 1000);
                    System.out.println("写第二份作业");
                    Thread.sleep(3 * 1000);
                    System.out.println("写第三份作业");
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new 写作业());
        t.start();
        Scanner scanner = new Scanner(System.in);
        scanner.nextLine();
        System.out.println("准备通知停止写作业");
        condition = false; // 不具备让 A 的 sleep 抛异常的功能
        System.out.println("已经通知停止写作业");
        t.join();
        System.out.println("已经停止写作业");
    }
}

注意:
使用普通状态位通知线程中断,当线程处于sleep中时,线程不会立即停止,condition变为false后,他会执行完当前任务才会停止。

JAVA内部的中断:

public void interrupt():中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,否则设置标志位
public static boolean interrupted():判断当前线程的中断标志位是否设置,调用后清除标志位(静态方法),清除标志位是为了不影响后续的通知。(推荐使用)
public boolean isInterrupted() :判断对象关联的线程的标志位是否设置,调用后不清除标志位

Thread.interrupted();//静态方法,调用后会清除标志位。
t.isInterrupted();//t线程调用后,不会清除标志位。

通过interrupt设置中断:

public class 如何通知一个线程停止 {
    static class 写作业 implements Runnable {
        @Override
        public void run() {
            Thread t = Thread.currentThread();
            while (!t.isInterrupted()) { 
                try {
                    System.out.println("写第一份作业");
                    Thread.sleep(3 * 1000);
                    System.out.println("写第二份作业");
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    // 通过这里捕获异常处理停止操作
                    break;
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new 写作业());
        t.start();
        
        Scanner scanner = new Scanner(System.in);
        scanner.nextLine();

        System.out.println("准备通知停止写作业");
        t.interrupt();
        System.out.println("已经通知停止写作业");
        t.join();
        System.out.println("已经停止写作业");
    }
}

注意:

  • 当任务run()中含有sleep类时,interrupt调用结束之后,线程内会收到一个异常InterruptedException,但此时t.isInterrupted仍是false.我们可以捕获InterruptedException异常,来处理这个中断通知。

  • 而run()中没有sleep类时,和普通设置true/false中断没有区别。即interrupt既可以应对普通情况,又可以应对像sleep这种特殊情况。

  • 可以通过Thread.interrupted()current.isInterrupted()来判断是否设置了停止标志位

Thread 的常见操作:
1) 启动线程 start:把线程放到就绪队列中,拥有争夺CPU的资格
2) 中断线程interrupt: 通知线程停止
3) join 等待一个线程停下来
4) 强制停止

currentThread():
public static Thread currentThread(); 返回当前线程对象的引用

Thread t = Thread.currentThread();

join():
public void join() 等待线程结束
public void join(long millis) 等待线程结束,最多等millis 毫秒
public void join(long millis, int nanos) 同理,但可以更高精度

yield():
Thread.yield(); 主动放弃CPU,但保留争夺CPU的资格,即优先让其他线程执行,前面没有其他线程时,再继续执行。

sleep():
public static void sleep(long millis) throws InterruptedException 休眠当前线程millis 毫秒
public static void sleep(long millis, int nanos) throws InterruptedException 可以更高精度的休眠

java中各种各样的sleep:

public static void main(String[] args) throws InterruptedException {
    Thread.sleep(10); // 毫秒
    TimeUnit.DAYS.sleep(10); // 天
    TimeUnit.HOURS.sleep(10); // 小时
}

注意:

  • Thread.sleep(毫秒):休眠—当前线程放弃CPU,把状态修改,x毫秒后,重新进入就绪态。进入就绪态后需要重新争夺CPU,所以,sleep的时间>=x毫秒,不是一个精确的x毫秒
  • sleep是放弃抢占CPU,退出就绪态,而yield(主动放弃)是还在就绪态,只不过是将优先级降到最低了,先等待其他线程执行结束。
线程的状态获取:

枚举:

enum Gender{
男,女
}
Gender gender = Gender.;

线程的状态通过枚举保存。

Thread.State[] values = Thread.State.values();

for(Thread.State state:values){
System.out.println(state);
}

线程状态和线程状态转移:

NEW:刚创建好,不具备争夺CPU的条件

RUNNABLE: 具备争夺CPU的条件(Ready),已经在CPU上了(Running); t.start()后主要在这个状态上(RUNNABLE)。

TERMINATED: 线程运行结束,但线程对象还在,即run()结束后就会 进入该状态。 如:t.join()后代表线程结束了,此时状态为TERMINATED。

BLOCKEDWAITINGTIMED_WAITING: 不再拥有抢占CPU的资格

线程状态转换
注意:

  • Java中将运行状态和就绪态统称为RUNNABLE,而要细分的话,要分为Ready和Running.
发布了54 篇原创文章 · 获赞 6 · 访问量 4794

猜你喜欢

转载自blog.csdn.net/glpghz/article/details/104711036