线程状态

线程状态

1.线程状态转换图

在这里插入图片描述

2.线程状态的进一步理解

new:Thread thread = new Thread(),线程对象一旦创建好了,就进入了新生状态;

就绪状态:当调用start()方法,线程立即进入就绪状态,但是这并不意味着该线程会立即被CPU调度执行;

运行状态:线程被CPU调度执行后,才算真正进入运行状态,线程才真正执行线程体的代码块;

阻塞状态:当调用sleep()、wait()方法或同步锁定时,线程进入阻塞状态,就会导致代码不会继续往下执行,只有当阻塞状态解除后,该线程才可以重新进入就绪状态,等待CPU的调度执行;

死亡:线程中断或者结束,一旦进入死亡状态,该线程就不能再次启动了。

3.线程方法

在这里插入图片描述

4.停止线程

A.不推荐使用JDK提供的stop()、destroy()方法。当你进入Thread类查看其中的方法时,你会发现这两个方法上画了一条横线,表示该方法已经废弃,不推荐使用;

B.推荐线程自己停下来;

C.建议使用一个标志位进行终止变量,例如:当flag = false,则线程终止。

D.代码如下:

//测试stop
//1.建议使用正常的停止,声明利用次数,尽量不要用死循环;
//2.建议使用标志位,就需要我们自己设置一个标志位;
//3.不要使用stop()或destroy()等过时或者JDK不推荐使用的方法;
public class TestStop implements Runnable {

    //1.设置一个标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while(flag) {
            System.out.println("运行————————线程" + i++);
        }
    }

    //自己设置一个公开的线程停止方法,通过改变标志位的值来控制线程的停止

    public void stop() {
        this.flag = false;
    }

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

        for (int i = 0; i < 1200; i++) {
            System.out.println("我是主线程" + i);
            if(i == 350) {
                //调用stop()方法,改变标志位的值
                testStop.stop();
                System.out.println("当循环次数达到" + i + "次,线程被停止了");
            }
        }
    }
}

运行结果:
在这里插入图片描述
如果能够得到以上运行结果,就证明线程停止成功。

5.线程休眠

A.sleep(时间)指定当前线程阻塞的毫秒数;

B.sleep存在异常InterruptedExcep;

C.sleep时间达到后,线程进入就绪状态;

D.sleep可以模拟网络延时,倒计时等;

E.每一个对象都有一个锁,sleep不会释放锁。(后期会说明原因)

F.代码:

//模拟延时:放大问题的发生性
public class TestSleep implements Runnable {
    private int tickets = 15;
    @Override
    public void run() {
        while(true) {
            if(tickets <= 0) {
                break;
            }
            //延时
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "买了" + tickets-- + "号票");
        }
    }

    public static void main(String[] args) {
        TestSleep saleFilms = new TestSleep();

        new Thread(saleFilms, "张三").start();
        new Thread(saleFilms, "李四").start();
        new Thread(saleFilms, "王五").start();
    }
}

补充:

在上一篇的线程实现中的卖电影的例子中,提出了线程的不安全,当时第二种方法,采用了延时,是为了放大线程不安全问题的发生性。

//模拟倒计时:十秒倒计时器
public class TestSleep2 {
    public static void main(String[] args) throws InterruptedException {
        countDown();
    }

    public static void countDown() throws InterruptedException {
        int num = 10;//倒计时的时间,长短可以自己定;

        while(true) {
            //这里会出现异常,我们采用抛出的方式;
            Thread.sleep(1000);
            System.out.println(num--);
            if(num <= 0) {
                break;
            }
        }
    }
}
import java.text.SimpleDateFormat;
import java.util.Date;

//模拟计时器:这里是进行的是从当前时间开始,进行计时
public class TestSleep2 {
    public static void main(String[] args) {
        //获取当前时间
        Date startTime = new Date(System.currentTimeMillis());

        while(true) {
            try {
                Thread.sleep(1000);
                String s = new SimpleDateFormat("HH:mm:ss").format(startTime);
                //打印当前时间
                System.out.println(s);
                //重新生成下一个时间
                startTime = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

6.线程礼让

A.礼让线程,让当前正在执行的线程暂停,但不会阻塞;

B.将线程从运行状态转为就绪状态;

C.让CPU重新调度,礼让不一定成功!看CPU心情,决定权掌握在CPU手里

D.代码:

//测试线程礼让:
//核心:礼让不一定成功,由CPU决定(调度算法);
public class TestYield {
    public static void main(String[] args) {
        doYield doYield = new doYield();

        new Thread(doYield, "B").start();
        new Thread(doYield, "A").start();
    }
}

class doYield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();//实现线程礼让;
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }
}

运行结果为:
在这里插入图片描述
如果得到了以上结果,就说明礼让成功了;但是也会出现礼让不成功的现象(多运行几次,就可以看到),如:
在这里插入图片描述
因此,礼让不一定成功,决定权掌握在CPU手里!

7.线程插队(Join)

A.把它理解为生活中的插队现象即可;

B.概念:Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞

C.代码:

//测试join()方法:想象成插队即可
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 500; i++) {
            System.out.println("我是VIP,我先执行");
            System.out.println("VIP执行了" + i + "次");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();

        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i = 1; i <= 100; i++) {
            if(i == 50) {
                thread.join();//抛出异常
            }
            System.out.println("主线程执行了" + i + "次");
        }
    }
}

观察程序的运行结果,会发现,当主线程运行到50次时,子线程会强行插队执行,并且主线程要等待子线程运行完毕后,才接着继续执行。

8.观测线程状态(Thread.State)

线程可以处于一下状态之一:

A.NEW

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

B.RUNNABLE

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

C.BLOCKED

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

D.WAITING

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

E.TIMED_WAITING

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

F.TERMINATED

​ 已退出的线程处于此状态,也可以理解为死亡的线程处于此状态。

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

G.代码:

//测试线程的状态
public class TestState implements Runnable {

    public static void main(String[] args) {

        TestState testState = new TestState();
        Thread thread = new Thread(testState);

        //观察状态
        Thread.State state = thread.getState();
        System.out.println(state);

        //观察启动后
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);

        while(state != Thread.State.TERMINATED) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //更新状态
            state = thread.getState();
            System.out.println(state);
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("*******************");
    }
}

程序运行结果:
在这里插入图片描述
这就是线程的五种状态,我们可以通过利用线程的这几种状态,来完成一些小事情,例如:

a.如果一个线程处于等待状态,就让它注销等;

b.如果一个线程在一定的时间里它都是等待状态,我们就可以让它崩溃,让它停止下来;

c.如果线程状态是TERMINATED,它就再也启动不了了。如果,再在TERMINATED后调用start()方法,会出错,如下图:
在这里插入图片描述
因此,死亡之后的线程是不可以再执行的。

本次讲述了线程状态,有关线程的知识点,仍在更新。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值