Java线程的创建及状态
什么是线程
在计算机中,一个任务就是一个进程。打开任务管理器,我们可以看见多个进程。如浏览器,QQ。线程是进程的再划分,是进程的一部分。一个进程可以只有一个线程(主线程),也可以有多个线程。拿浏览器举例,打开浏览器的多个网页,一个网页在播放音乐,一个网页在播放视频,一个网页在浏览博客。每个网页有不同的分工,这些浏览器的每个子任务就是一个线程。
线程是更轻量的进程,创建一个线程的消耗要低于创建一个进程,且同一进程的不同线程之间可以共享资源,效率更高。通过多线程可以更好地实现并发编程。
进程vs线程
- 进程包含线程,进程是线程的一部分,一个进程中至少包含一个线程。
- 进程与进程之间不能共享资源,同一个进程的线程之间可以共享资源。
- 进程是系统分配资源的最小单位,线程是系统调度执行的最小单位。
- 多进程稳定性高于多线程,一个进程的崩溃不会影响其他线程;多线程下一个线程的崩溃可能影响该进程。
创建线程
一个线程至少包含一个进程,main()
就是一个线程,我们还可以在里面创建多个线程。
1.继承Thread
类,重写run()
方法
1 | public class Main { |
2.创建Thread
实例,实现Runnable
接口
1 | public class Main { |
3.其他变形
- 匿名内部类创建Thread子类对象
1 | Thread t1 = new Thread() { |
- 匿名内部类创建Runnable子类对象
1 | Thread t2 = new Thread(new Runnable() { |
- lambda表达式创建Thread子类对象
1 | Thread t4 = new Thread(() -> { |
Thread
方法
常见构造方法
构造方法 |
---|
Thread() 分配一个新的 Thread 对象。 |
Thread(Runnable target) 分配一个新的 Thread 对象。 |
Thread(Runnable target, String name) 分配一个新的 Thread 对象,name为新线程的名字。 |
Thread(String name) 分配一个新的 Thread 对象,name为新线程的名字。 |
启动一个线程.start()
Thread对象对创建后,并没有启动线程,执行该指令后才会真正创建一个线程。即内核中创建了一个内存控制块PCB。
中断一个线程
方法1:自定义变量作为标志位
1 | //自定义变量flag作为标志位 |
方法2:interrupted()
方法中断线程
1 | public class ThreadDemo3 { |
Thread.currentThread().isInterrupted()
获取当前线程是否被中断;interrupted()
向线程发出中断请求。
Thread收到通知方式有两种:①当线程因wait/sleep/join等方法处于堵塞状态时,以 InterruptedException
异常的形式通知。②isInterrupted()
标志位置为true.
等待一个线程.join()
执行该指令,会使该线程执行结束后再执行下一线程,即将并发编程变成了串行。比如用某软件下载一部电影,可以边下载边观看,当执行该指令后,就要等下载完后再看了~
休眠一个线程sleep()
让线程进入休眠状态,进入休眠状态的指令,他的属性isAlive()
为Timed Waiting。线程状态会稍后介绍到。
线程状态
注意,这里我们说的是java线程的六种状态。利用isAlive
属性可以观察线程的状态,线程有以下6种状态:
- New:新创建的线程,但未执行
start()
,线程没有存活; - Runnable:运行中的线程,正在执行
run()
方法的Java代码; - Blocked:运行中的线程,因为某些操作被阻塞而挂起;
- Waiting:运行中的线程,因为某些操作在等待中,如执行
wait()
方法; - Timed Waiting:运行中的线程,因为执行
sleep()
方法正在计时等待; - Terminated:线程结束,线程没有存活。
线程状态转换
线程被创建出来,处于New状态。调用start方法后,处于Runnable状态。当线程获取不到锁时,处于Blocked状态,直到获取到锁后进入Runnable状态。运行的线程调用wait或join方法后会进入Waiting状态,直到唤醒通知后进入Runnable状态。调用带有超时参数的方法后会进入Timed Waiting状态,直到时间到后进入Runnable状态。运行的线程执行完run方法或出现异常后进入Terminated状态。
与操作系统中的进程状态不同,java没有就绪态。操作系统中,一个进程调用start后并没有直接运行,而是进入就绪态,当获取到cpu时间片后进入运行态。我们可以认为在java中,就绪态和运行态同属于Runnable。