目录
1.认识线程
1.1 线程是什么呢
线程都了解吧,就相当一个“执行流”,每一个线程都会按顺序执行自己的代码。而多线程则是同时执行很多份代码。
就比如公司接了一个项目,这个项目分好多模块,如果你一个人做就会非常耗时,但如果跟你的同事一起做,那么就有三个人做这个项目,也就是三个“执行流”共同完成任务。
这种情况就是多线程,将一个人大任务分解为不同的小任务,交给不同的执行流分别排队执行,因为你同事是你喊来帮忙的,所以你自己通常被称为主线程
1.2为什么要有线程
首先,“并发编程”成为主流需要
- 单核CPU发展遇到瓶颈,提高算力的话 ,就需要用到多核CPU,而并发编程能更好的充分利用多核CPU
- 有些任务场景需要等待IO,为了等待IO的时间能有时间去做一些其他事情,也需要用到并发编程
其次,虽然多进程也能实现并发编程,但是线程比进程更轻量
- 创建线程比进程更快
- 销毁线程比进程更快
- 调度线程比进程更快
最后, 人们不满足于线程,于是又有了线程池跟协程
1.3进程和线程的区别
- 进程是包含线程的,每一个进程都至少有一个线程,即主线程。
- 进程和进程之间不共享内存空间,但同一个进程的线程之间是共享内存空间的。
- 进程是系统分配资源的最小单位,线程是系统调度的最小单位
1.4Java线程和操作系统线程的关系
线程是操作系统中的概念,是操作系统内核实现了线程机制,并且对用户层提供了一些API供用户使用
-
Java标准库中的Thread类就可以看作是对操作系统提供的API进行了进一步的抽象和封装
1.5如何创建线程
(1)继承Thread类
class MyThread extends Thread {@Overridepublic void run () {System . out . println ( " 这里是线程运行的代码 " );}}
创建MyThread类的实例
MyThread t = new MyThread();
调用start方法启动线程
t.start();
(2)实现 Runnable接口
class MyRunnable implements Runnable {@Overridepublic void run () {System . out . println ( " 这里是线程运行的代码 " );}}
创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.
Thread t = new Thread(new MyRunnable());
t.start();
(3)一些其他变形
// 使用匿名类创建 Thread 子类对象Thread t1 = new Thread () {@Overridepublic void run () {System . out . println ( " 使用匿名类创建 Thread 子类对象 " );}};
// 使用匿名类创建 Runnable 子类对象Thread t2 = new Thread ( new Runnable () {@Overridepublic void run () {System . out . println ( " 使用匿名类创建 Runnable 子类对象 " );}});
// 使用 lambda 表达式创建 Runnable 子类对象Thread t3 = new Thread (() -> System . out . println ( " 使用匿名类创建 Thread 子类对象 " ));Thread t4 = new Thread (() -> {System . out . println ( " 使用匿名类创建 Thread 子类对象 " );});
2.Thread类和常用方法
Thread类是JVM用来管理线程的一个类,每一个执行流都要有一个对象去描述,而Thread类的对象就是用来描述一个线程执行流的,JVM会将这些Thread对象组织起来,用于线程调度,线程管理。
2.1 Thread的常用构造方法
方法 | 说明 |
Thread()
|
创建线程对象
|
Thread(Runnable target)
|
使用
Runnable
对象创建线程对象
|
Thread(String name)
|
创建线程对象,并命名
|
Thread(Runnable target, String name)
|
使用
Runnable
对象创建线程对象,并命名
|
2.2Thread的常见属性
属性 | 获取方法 |
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 (JVM会在一个进程的所有非后台线程结束后 才会结束运行) | isDaemon() |
是否存活(run方法是否运行结束) | isAlive() |
是否被中断 | isInterrupted() |
2.3启动一个线程star()
run方法主要是给线程提供要做的事情的指令清单,而start方法才是让线程去执行
2.4 中断一个线程
方法
|
说明
|
public void interrupt()
|
中断对象关联的线程,如果线程正在阻塞,则以异常方式通知, 否则设置标志位
|
public static boolean
interrupted()
|
判断当前线程的中断标志位是否设置,调用后清除标志位
|
public boolean
isInterrupted()
|
判断对象关联的线程的标志位是否设置,调用后不清除标志位
|
2.5等待一个线程
方法
|
说明
|
public void join()
|
等待线程结束
|
public void join(long millis)
|
等待线程结束,最多等
millis
毫秒
|
public void join(long millis, int nanos)
|
同理,但可以更高精度
|
2.6 休眠当前线程
方法
|
说明
|
public static void sleep(long millis) throws InterruptedException
|
休眠当前线程
millis
毫秒
|
public static void sleep(long millis, int nanos) throws
InterruptedException
|
可以更高精度的休眠
|
3.线程的状态
- NEW: 安排了工作, 还未开始行动
-
RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作
-
BLOCKED: 表示排队等着其他事情
- WAITING: 表示排队等着其他事情
- TIMED_WAITING: 表示排队等着其他事情
- TERMINATED: 工作完成了.
但是这三个等待是有区别的:
BLOCKED 表示等待获取锁, WAITING 和 TIMED_WAITING 表示等待其他线程发来通知.
TIMED_WAITING 线程在等待唤醒,但设置了时限; WAITING 线程在无限等待唤醒