线程与多线程必会的知识
本文主要分为三个方面来介绍:
- 线程和多线程
- 线程的运行和创建
- 线程的状态
1 线程与多线程
线程是什么?线程(Thread)是一个对象(Object)。用来干什么?java线程(也称JVM线程)是java进程内允许许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。
Java 程序采用多线程方式来支持大量的并发请求处理,程序如果在多线程方式执行下,其复杂度远高于单线程串行执行。那么多线程:指的是这个程序(一个进程)运行时产生了不止一个线程。
为啥使用多线程?
- 适合多核处理器。一个线程运行在一个处理器核心上,那么多线程可以分配到多个处理器核心上,更好地利用多核处理器。
- 防止阻塞。将数据一致性不强的操作使用多线程技术(或者消息队列)加快代码逻辑处理,缩短响应时间。
聊到多线程,多半会聊并发与并行,咋理解并区分这两个的区别呢?
- 类似单个 CPU ,通过 CPU 调度算法等,处理多个任务的能力,叫并发。
- 类似多个 CPU ,同时并且处理相同多个任务的能力,叫做并行。
2 线程的运行与创建
2.1 线程的创建
java 创建线程对象有两种方法:
- 继承Thread类创建线程对象。
- 实现Runnable 接口类创建线程对象。
新建MyThread对象,代码如下:
public class MyThread extends Thread {
@Override // 可以省略
public void run() {
System.out.println("MyThread 的线程对象正在执行任务");
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
System.out.println("MyThread 的线程对象 " + thread.getId());
}
}
}
MyThread 类继承了 Thread 对象,并重写(Override)了 run 方法,实现线程里面的逻辑。main 函数是使用 for 语句,循环创建了 10 个线程,调用 start 方法启动线程,最后打印当前线程对象的 ID。
run 方法和 start 方法的区别是什么呢? run 方法就是跑的意思,线程启动后,会调用 run 方法。 start 方法就是启动的意思,就是启动新线程实例。启动线程后,才会调线程的 run 方法。
同理,实现Runnable接口类创建线程对象也很简单,只是不同的形式。新建的MyThreadBrother代码如下:
public class MyThreadBrother implements Runnable {
@Override // 可以省略
public void run() {
System.out.println("MyThreadBrother 的线程对象正在执行任务");
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new MyThreadBrother());
thread.start();
System.out.println("MyThreadBrother 的线程对象 " + thread.getId());
}
}
}
2.2 线程的运行
在运行上面两个小 demo 后,JVM 执行了 main 函数线程,然后在主线程中执行创建了新的线程。正常情况下,所有线程执行到运行结束为止。除非某个线程中调用了 System.exit(1) 则被终止。
3.线程的状态
新建MyThreadinfo类,打印线程对象属性,代码如下:
public class MyThreadInfo extends Thread {
@Override // 可以省略
public void run() {
System.out.println("MyThreadInfo 的线程实例正在执行任务");
// System.exit(1);
}
public static void main(String[] args) {
MyThreadInfo thread = new MyThreadInfo();
thread.start();
System.out.print("MyThreadInfo 的线程对象 \n"
+ "线程唯一标识符:" + thread.getId() + "\n"
+ "线程名称:" + thread.getName() + "\n"
+ "线程状态:" + thread.getState() + "\n"
+ "线程优先级:" + thread.getPriority());
}
}
线程是一个对象,它有唯一标识符 ID、名称、状态、优先级等属性。线程只能修改其优先级和名称等属性 ,无法修改 ID 、状态。ID 是 JVM 分配的,名字默认也为 Thread-XX,XX是一组数字。线程初始状态为 NEW。
线程优先级的范围是 1 到 10 ,其中 1 是最低优先级,10 是最高优先级。不推荐改变线程的优先级,如果业务需要,自然可以修改线程优先级到最高,或者最低。
线程的状态实现通过 Thread.State 常量类实现,有 6 种线程状态:new(新建)、runnnable(可运行)、blocked(阻塞)、waiting(等待)、time waiting (定时等待)和 terminated(终止)。
线程状态流程大致如下:
- 线程创建后,进入 new 状态
- 调用 start 或者 run 方法,进入 runnable 状态
- JVM 按照线程优先级及时间分片等执行 runnable 状态的线程。开始执行时,进入 running 状态
- 如果线程执行 sleep、wait、join,或者进入 IO 阻塞等。进入 wait 或者 blocked 状态
- 线程执行完毕后,线程被线程队列移除。最后为 terminated 状态。
浙公网安备 33010602011771号