前言
在并发编程中,有两个基本执行单元:进程(processes) 和 线程(thread)。在 Java 编程语言中,并发编程主要涉及线程。但是,进程也很重要。
目录
一、概念
进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是线程的容器,是程序的实体。程序是指令、数据及其组织形式的描述。
线程:是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
进程——资源分配的最小单位。指在系统中正在运行的一个应用程序。
线程——cpu调度/程序执行的最小单位。系统分配处理器时间资源的基本单元。
二、使用
启动线程
启动线程方式有两种:
扩展自Thread类,重写run()方法,使用start()方法启动线程。
1 | public class UseThread extends Thread{ |
实现Runnable接口,实现run()方法,使用先创建含Runnable的Thread对象,然后执行start方法。
1 | public class UseRunnable implements Runnable{ |
start()方法和run()方法的区别:
start()方法会去调用native方法开启线程,只能调用一次,多次启动线程是不合法的。
run()方法是业务逻辑代码实现的地方,相当于类的成员方法,可调用多次且可单独执行。
注:Thread类是Java对线程的抽象,Runnable是对任务和业务逻辑的抽象。方法
run即在线程中执行的代码
停止线程
推荐使用interrupt()方法停止线程。
stop():强制停止,可能造成资源回收不了,不安全。
interrupt():中断线程,调用后线程处于就绪状态,而不是终止状态。其实是设置中断标志为true,由程序员决定线程如何响应中断,安全。
注:interrupt (中断) 表示线程应该停止正在执行的操作并执行其他操作。由程序员决定线程如何响应中断。
线程是否中断
线程中断状态下中断标志为true,否则为false。检查线程是否是中断方法:
isInterrupted():检查中断时,不会更改中断标志。
Thread类的静态方法 interrupted():检查中断时,会清除中断标志,即中断标志变为false。
注:任何通过抛出
InterruptedException退出的方法如sleep(),都会在执行此操作时清除中断状态,需要通过再一次调用interrupt()方法 ,总是可以立即再次设置中断状态。jdk线程是协作式,而不是抢占式。
线程顺序执行
join() 方法允许当前线程等待另一个线程t的完成后再执行,因此可实现线程顺序执行。
1 | t.join(); |
线程优先级
设置线程优先级setPriority(),范围1~10,优先级越高分配cpu时间片要多,但实际效果与操作系统有关,不能用来控制线程执行顺序。
守护线程
守护线程:会随着用户线程结束而终止。
在执行start前,调用setDaemon(true)可设置线程为守护线程。
1 | t.setDaemon(true); |
注:守护线程中的 finally 代码块不一定执行。
三、状态
Java中线程的状态分为6种:
初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
阻塞(BLOCKED):表示线程阻塞于锁,使用了synchronized。
等待(WAITING):进入该状态的线程需要无限期等待其他线程做出一些特定动作(通知或中断)。
等待超时(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
终止(TERMINATED):表示该线程已经执行完毕。
状态之间的变迁如下图所示:

注:调用
yield()该线程会让出cpu执行权,但不会释放锁。sleep()方法也不会释放锁。