目录
获取当前线程引用
休眠当前线程
线程的状态
1.NEW
2.TERMINATED
3.RUNNABLE
4.WAITING
5.TIMED_WAITING
6.BLOCKED
多线程的意义
单线程
多线程
获取当前线程引用
public static Thread currentThread();
这个方法返回当前线程的引用。但是我们会对static有疑惑,这其实是一个静态方法,更好的说法是这是一个类方法,调用这个方法,不需要实例,直接通过类名来调用。
可以直接通过Thread.currentThread(),不一定要t.currentThread()
在哪个线程中调用,就能获取到哪个线程的实例.
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}
}
休眠当前线程
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之类的方法。
多线程最核心的地方:抢占式执行,随机调度。
多线程的意义
我们写个案例来了解一下多线程的意义:
我们通过写一个运算量很大的任务,看一下多线程和单线程的区别
单线程
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获取开始和结束的时间,打印出来两者之差,粗略的能得到运行的时间
多线程
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这些核心已经都满载了,这个时候启动更多的线程也啥用)