0%

Java线程

前言

在并发编程中,有两个基本执行单元:进程(processes) 和 线程(thread)。在 Java 编程语言中,并发编程主要涉及线程。但是,进程也很重要。

目录

一、概念

进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是线程的容器,是程序的实体。程序是指令、数据及其组织形式的描述。

线程:是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

进程——资源分配的最小单位。指在系统中正在运行的一个应用程序。

线程——cpu调度/程序执行的最小单位。系统分配处理器时间资源的基本单元。

二、使用

启动线程

启动线程方式有两种:

扩展自Thread类,重写run()方法,使用start()方法启动线程。

1
2
3
4
5
6
7
8
9
10
11
12
public class UseThread extends Thread{
@Override
public void run() {
super.run();
//do my work
System.out.println("I am extends Thread");
}
}

// 调用
UseThread useThread = new UseThread();
useThread.start();

实现Runnable接口,实现run()方法,使用先创建含Runnable的Thread对象,然后执行start方法。

1
2
3
4
5
6
7
8
9
10
public class UseRunnable implements Runnable{
@Override
public void run() {
System.out.println("I am implements Runnable");
}
}

// 使用UseRunnable构建一个Thread然后执行
UseRunnable useRun = new UseRunnable();
new Thread(useRun).start();

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
2
t.setDaemon(true);
t.start()

注:守护线程中的 finally 代码块不一定执行。

三、状态

Java中线程的状态分为6种:

  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。

  2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

  3. 阻塞(BLOCKED):表示线程阻塞于锁,使用了synchronized。

  4. 等待(WAITING):进入该状态的线程需要无限期等待其他线程做出一些特定动作(通知或中断)。

  5. 等待超时(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。

  6. 终止(TERMINATED):表示该线程已经执行完毕。

状态之间的变迁如下图所示:

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

总结