java线程的七种状态和三种中断


在这里插入图片描述

新建状态(New)

当用new操作符创建一个线程后, 例如new Thread(),此时线程处在新建状态。 当一个线程处于新建状态时,线程中的任务代码还没开始运行。

就绪状态(Runnable)

也被称为“可执行状态”。一个新创建的线程并不自动开始运行,要执行线程,必须==调用线程的start()==方法。当调用了线程对象的start()方法即启动了线程,此时线程就处于就绪状态。

处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他就绪线程竞争CPU,只有获得CPU使用权才可以运行线程。比如在单核心CPU的计算机系统中,不可能同时运行多个线程,一个时刻只能有一个线程处于运行状态。对与多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度执行。

除了调用start()方法后让线程变成就绪状态,一个线程阻塞状态结束后也可以变成就绪状态,或者从运行状态变化到就绪状态。

运行状态(Running)

线程获取到CPU使用权进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。真正开始执行线程的run()方法的内容。

阻塞状态(Blocked)

线程在获取锁失败时(因为锁被其它线程抢占),它会被加入锁的同步阻塞队列,然后线程进入阻塞状态(Blocked)。阻塞状态的线程不会释放锁处于阻塞状态(Blocked)的线程放弃CPU使用权,暂时停止运行

public class AddNumber {
    private int num=0;
    public void add(String name) throws InterruptedException {
            num=100;   //这里num值改为100
            Thread.sleep(1000);  //线程暂睡眠1秒,即进入阻塞状态1秒
            //伪代码:另一个线程恰巧在这一秒的时间里将num=100修改了num=200;
            //一秒之后,线程苏醒,继续运行run方法。但此时从内存中读出来的num值是200
            //对于该线程来说,这里的num=200就属于脏读。
            System.out.println(num);

待其它线程释放锁之后,阻塞状态(Blocked)的线程将在次参与锁的竞争,如果竞争锁成功,线程将进入就绪状态(Runnable) 。比如调用线程的调用线程的sleep()方法

等待状态(WAITING)

或者叫条件等待状态,当线程的运行条件不满足时,通过锁的条件等待机制(调用锁对象的==调用线程的wait()==或显示锁条件对象的await()方法)让线程进入等待状态(WAITING)。处于等待状态的线程将不会被cpu执行,除非线程的运行条件得到满足后,其可被其他线程唤醒,进入阻塞状态(Blocked)。调用不带超时的Thread.join()方法也会进入等待状态。

限时等待状态(TIMED_WAITING)

限时等待是等待状态的一种特例,线程在等待时我们将设定等待超时时间,如超过了我们设定的等待时间,等待线程将自动唤醒进入阻塞状态(Blocked)或就绪状态(Runnable) 。在调用Thread.sleep()方法,带有超时设定的Object.wait()方法,带有超时设定的Thread.join()方法等,线程会进入限时等待状态(TIMED_WAITING)。

死亡状态(TERMINATED)

线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

使用退出标志中断

public class test1 {

    public static volatile boolean exit =false;  //退出标志
    
    public static void main(String[] args) {
        new Thread() {
            public void run() {
                System.out.println("线程启动了");
                while (!exit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("线程结束了");
            }
        }.start();
        
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exit = true;//5秒后更改退出标志的值,没有这段代码,线程就一直不能停止
    }
}

使用 interrupt 方法中断

interrupt() + isInterrupted()+InterruptedException

public class ExceptionThread extends Thread {
    @Override
    public void run() {
        try {
            throw new InterruptedException();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0;i<10000;i++){
            //线程中断并不意味着线程结束,interrupt()只是改变了【isInterrupted()方法的返回值】中断标志的状态--(并且抛出InterruptedException异常而已),它不影响run()方法的运行
            if (this.isInterrupted()){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("捕捉到了异常:该线程被中断了");
                    //e.printStackTrace();
                }
                System.out.println("我发生了线程中断,突然 over 掉了");
                break;
                //return;
            }
            System.out.println(i);
        }
    }
}

测试代码

public class Run {
    public static void main(String arg[]) throws InterruptedException {
        ExceptionThread exceptionThread=new ExceptionThread();
        exceptionThread.start();
        //主线程的休眠不会影响子线程的执行
        Thread.sleep(100);
        //主线程休眠0.1秒后,对子线程exceptionThread执行中断操作
        exceptionThread.interrupt();
    }
}

使用stop方法中断

jdk中标为过期的方法,强烈不建议使用
强制让线程停止,则有可能使一些清理性的工作得不到完成。对锁定的对象进行了解锁,导致数据得不到同步的处理,出现数据不一致的问题

suspend()方法+resume()方法的缺点

suspend()方法暂停线程,resume()方法恢复线程----二者使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步的对象------常见于让a线程start()后(a线程得到了SynchronizedObjectSole对象的pstring()方法的锁)又suspend暂停a线程,但程序却忘了resume恢复a线程,就相当于a线程得到的那把锁的钥匙丢了。则锁就永远不会被释放了

public class SynchronizedObjectSole {
    synchronized public void pstring(){
        System.out.println("start");
        if(Thread.currentThread().getName().equals("a")){
            Thread.currentThread().suspend();
            System.out.println("a永远suspend");
        }
        System.out.println("end");
    }
}

公共的同步对象的独占代码测试

public class Run {
    public static void main(String arg[]) throws InterruptedException {
            final SynchronizedObjectSole sos=new SynchronizedObjectSole();
            Thread thread1=new Thread(){
                @Override
                public void run(){
                    sos.pstring();
                }
            };
            thread1.start();
            Thread.sleep(1000);
            Thread thread2=new Thread(){
                @Override
                public void run(){
                    System.out.println("线程2永远无法使用sos对象的pstring()方法,因为它被a线程独占了");
                    sos.pstring();
                }
            };
            thread2.start();
    }
}

中断的综合测试

public class test1 {

    static volatile boolean flag = true;

    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("开始休眠");
                try {
                    Thread.sleep(100 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束休眠,开始死循环");
                while (flag) {
                }
                System.out.println("------------------子线程结束------------------");
            }
        });
        thread.start();

        Scanner scanner = new Scanner(System.in);
        System.out.println("输入1抛出一个中断异常,输入2修改循环标志位,输入3判断线程是否阻塞,输入其他结束Scanner\n");
        while (scanner.hasNext()) {
            String text = scanner.next();
            System.out.println("你输入了:" + text + "\n");
            if ("1".equals(text)) {
                thread.interrupt();
            } else if ("2".equals(text)) {
                flag = false; //如果不设为false,主线程结束后子线程仍在运行
            } else if ("3".equals(text)) {
                System.out.println(thread.isInterrupted());
            } else {
                scanner.close();
                break;
            }
        }
        System.out.println("------------------主线程结束------------------");
    }
}

摘抄自:
1.https://www.cnblogs.com/myseries/p/10918819.html
2.https://baijiahao.baidu.com/s?id=1626410873162104506&wfr=spider&for=pc

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值