JavaEE初阶:Java线程的状态

目录

获取当前线程引用

休眠当前线程

线程的状态

1.NEW

2.TERMINATED

3.RUNNABLE

4.WAITING

5.TIMED_WAITING

6.BLOCKED

多线程的意义

单线程

多线程


获取当前线程引用

java 复制代码
public static Thread currentThread(); 

这个方法返回当前线程的引用。但是我们会对static有疑惑,这其实是一个静态方法,更好的说法是这是一个**类方法,**调用这个方法,不需要实例,直接通过类名来调用。

可以直接通过Thread.currentThread(),不一定要t.currentThread()

在哪个线程中调用,就能获取到哪个线程的实例.

java 复制代码
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
   }
}

休眠当前线程

java 复制代码
public static void sleep(long millis)

让线程休眠,本质上就是让这个线程不参与调度了,不去cpu上执行

线程的状态

状态是针对当前的线程调度的情况来描述的

咱们现在认为,线程是调度的基本单位了 状态更应该是线程的属性。

在Java对于线程的状态,进行了细化:

1.NEW

创建了Thread对象,但是还没调用start(内核里还没创建对应的PCB)

2.TERMINATED

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

一但内核里的线程PCB消亡了,此时代码中t对象也就没啥用了,但是还存在

Java中的对象有生命周期,自有其规则,内核的线程释放的时候无法保证Java代码中t对象也立刻释放

因此势必就会存在内核的PCB没了,但是代码中的t还在这样的情况,此时就需要通过特定的状态,来把t对象标识成"无效"

3.RUNNABLE

a)正在CPU上执行的

b)在就绪队列里,随时可以去CPU上执行

4.WAITING

5.TIMED_WAITING

6.BLOCKED

通过getState可以获取当前进程的状态:​​​​​​​

此处能看到RUNNABLE,主要就是因为当前线程run里面,没有写任何sleep之类的方法。

多线程最核心的地方:抢占式执行,随机调度。

多线程的意义

我们写个案例来了解一下多线程的意义:

我们通过写一个运算量很大的任务,看一下多线程和单线程的区别

单线程

java 复制代码
public class demo {
    public static void main(String[] args) {
        serial();
    }

    public static void serial(){
        long beg = System.currentTimeMillis();

        long a = 0;
        for(long i = 0 ; i < 100_0000_0000L ; i++){
            a++;
        }

        long b = 0;
        for(long j = 0 ; j < 100_0000_0000L ; j++){
            b++;
        }
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end-beg) + "ms");
    }
}

执行时间6599ms

进程已结束,退出代码0

通过运行一个重复一百亿的加法,可以得到这个线程的运行时间

用currentTimeMilis获取开始和结束的时间,打印出来两者之差,粗略的能得到运行的时间

多线程

java 复制代码
    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 j = 0 ; j < 100_0000_0000L ; j++){
                b++;
            }
        });

        long beg = System.currentTimeMillis();
        t1.start();
        t2.start();
        long end = System.currentTimeMillis();
        System.out.println("执行时间" + (end-beg) + "ms");
        
    }

执行时间0ms

进程已结束,退出代码0

通过Lambda表达式新建两个线程,注意此时有main、t1、t2三个线程,我们把刚刚main线程的工作放在t1、t2中,这样在两个线程中分别进行循环

但是为什么最后的执行时间是0ms呢,是因为线程是独立运行的,执行时间的判定是在main线程中单独完成,也就是没有等待t1t2执行完再返回时间,所以我们需要加入join来让main线程等待其完成:

可以看到时间近乎缩短了一半,这就是多线程相对于单线程的优势,可以更加充分的利用CPU多核心的能力,但是时间又不是刚好缩短了一半:

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

但是不是说使用多线程,就能一定提高效率:

1.是否是多核(现在的CPU基本都是多核了)

2.当前核心是否空闲(如果CPU这些核心已经都满载了,这个时候启动更多的线程也啥用)

相关推荐
m0_5719575842 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程3 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go