线程的状态

目录

1.线程的状态

2.线程状态的转换

3.多线程的意义


1.线程的状态

线程是操作系统调度的基本单位,线程的状态是一个枚举类型

通过遍历可以打印得到线程的状态的名称

public class ThreadDemo12 {
    public static void main(String[] args) {
        for (Thread.State state : Thread.State.values() 
             ) {
            System.out.println(state);         
        }
    }
}

 

Java中对线程的状态做了细化,一共有六个状态

1.1 NEW

仅仅只创建了Three对象,还没调用start方法,内核没有创建对应的PCB

1.2 TERMINATED

表示内核中的PCB已经执行完了,但是Thread对象还在

1.3 RUNNABLE

可运行的,包含正在CPU上执行的,或者正在就绪队列中,随时可以取CPU上执行的

1.4 WAITING

表示线程阻塞

1.5 TIMED_WAITING

表示线程阻塞

1.6 BLOCKED

表示线程阻塞

后三个状态是不同原因的阻塞

2.线程状态的转换

线程状态的大致转换如图

主线是由NEW->RUNNALBE->TERMINATED,从线程创建到线程执行再到线程结束

支线就是在三种不同的操作下引起的阻塞状态,是在RUNNABLE状态时进行的

下面结合代码可以直观地看到线程的状态

public class ThreadDemo12 {
    public static void main(String[] args) {
        Thread t  = new Thread(()->{
            for (int i = 0; i < 10000000; i++) {

            }
        });
        System.out.println("t.start之前:"+t.getState());
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("t.start之后:"+t.getState());
    }
}

 TERMINATED的存在是因为内核线程释放的时候,不能保证线程对象也立即释放,因此存在线程释放后线程对象还存在,生命周期是不一致的,所以需要通过一个特定的状态来将线程对象标识成无效,不能再使用,也不能重新start,一个线程只能创建一次PCB

线程结束后,无法再利用多线程了,但是线程对象还存在,还可以用线程对象调用一些方法和属性

接下来查看RUNNABLE状态:

这里能看到RUNNABLE状态是因为run方法中没有sleep之类的方法

 如果run方法中有sleep,那么线程的状态就是RUNNABLE或者TIMED_WAITING,取决于线程运行到哪个环节了

public static void main(String[] args) {
        Thread t  = new Thread(()->{
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        System.out.println("t.start之前:"+t.getState());
        t.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("线程执行中的状态:"+t.getState());
        }
        try {
            t.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("t.start之后:"+t.getState());
    }

run方法中加sleep后,循环打印start后线程状态的结果 

多次获取后我们看到线程状态从RUNNABLE转换到TIMED_WAITING,当前获取到的状态是什么,完全取决于操作系统的调度,获取状态的瞬间,线程对象是在执行还是在休眠!!

还有两种阻塞I(WAITING/BLOCKED)状态后续写到对应方法再进行叙述

3.多线程的意义

通过下面代码感受多线程和单线程之间执行速度的差别

程序分为cpu密集和IO密集,cpu密集包含大量的加减乘除运算,IO密集涉及到读写文件,读写控制台,读写网络,这里我们通过cpu密集的程序来感受多线程的特点

假设当前有两个变量需要把他们各自自增1000W次,分别通过单线程和多线程实现

可以通过一个线程,先对a自增,后对b自增

也可以多线程,分别对ab自增

先看单线程执行时间

public class ThreadDemo13 {
    public static void main(String[] args) {
        serial();
    }
    public static void serial(){
        long beg = System.currentTimeMillis();
        long  a = 0;
        for (long i = 0; i < 100_000_0000L; i++) {
            a++;
        }
        long  b = 0;
        for (long i = 0; i < 100_000_0000L; i++) {
            b++;
        }
        long end = System.currentTimeMillis();
        System.out.println("执行时间: "+(end-beg)+" ms");
    }
}

单线程多次运行后,执行的时间 

public static void concurrency(){

        Thread t1 = new Thread(()->{
            long a =  0;
            for (long i = 0; i < 100_0000_0000L; i++) {
                a++;
            }
        });
        Thread t2 = new Thread(()->{
            long b =  0;
            for (long i = 0; i < 100_0000_0000L; i++) {
                b++;
            }
        });
        long beg = System.currentTimeMillis();
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long end = System.currentTimeMillis();
        System.out.println("并发执行耗时:"+(end-beg)+" ms");
    }

注意:如果在调用两个start后没有加join方法等待t1t2线程执行结束,那么执行时间就会使0ms

因为当主线和t1t2线程并发执行时,谁先执行是不确定的,如果刚调完t1t2,main线程就继续执行,那么打印的时间就是0,因此要先让两个线程执行结束,再继续进行主线程

在主线程调用join方法只能保证主线程是最后结束的,另外的两个线程执行的顺序和谁先结束谁后结束是不确定的 

 并发执行后,多次执行的时间

多线程执行的时间相比于串行执行时间,明显缩短了,为什么没有缩短一半呢?

因为保证不了并行执行!在执行过程中会经历很多次的调度,过程中可能是并发执行(同一时间间隔上在一个核心上执行)或者并行执行(在多个核心上同时执行)

线程调度自身也有时间消耗,因此很难让时间正好是串行调度的一半,即使是这样,多线程执行任然有很大的意义

多线程在cpu密集型的任务中,有非常大的作用,可以充分利用cpu的多核资源,从而加快程序的运行效率

也不是多线程就一定能提高效率,要看是否是多核,二是当前核心是否空闲,如果cpu当前已经满载了,使用多线程也不能提高效率

在IO密集型任务中.经常看到"程序未响应".比如启动一个比较大的游戏的时候,要加载大量的数据文件,涉及到大量的读硬盘操作,阻塞了界面响应,多线程也是能起到一定的改善作用(让一个线程负责IO,另一个线程来响应用户的操作)

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YoLo♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值