多线程
线程概述
进程: 它是应用程序的执行实例, 它有独立的内存空间和系统资源。
线程(thread): 是 CPU 调度和分派的基本单位,它是 进程中执行运算的最小单位, 可完成一个独立的顺序控制流程 。
多线程概述
多条线程。
优势:提升 CPU 利用率。
在 Java 中提供的多线程是一种 “抢占式” 的多线程,哪个线程抢占到了 CPU 资源,谁就可以执行。
单核 CPU: 只能有一个线程处理,是一个假的多线程,实际上就是一个线程经过 CPU 分配,一会执行一下其中一个程序流程,一会又去执行另一个程序流程。(“同时” 处理不同的程序流程)
多核 CPU: 每个核都可以有一条线程来处理不同的程序流程。(同时处理不同的程序流程)
主线程
一个进程,至少有一个线程,这个线程被称为主线程。
在 Java 中的主线程:main
java.lang.Thread
-
currentThread() : Thread 获取当前线程
-
getName() : String 获取当前线程的名字
-
setName(name:String) : void 设置线程的名字
线程创建和启动
继承Thread接口
-
编写自定义线程类,继承 Thread 类
-
重写 run 方法,编写线程要执行的内容
-
根据自定义线程类创建线程对象
-
启动线程
【面试题】start方法和run方法区别?
start 方法是用于启动线程,这样的话才会创建一个新的线程。
run 方法是线程要执行的内容的方法,如果直接调用 run 方法,实际上只是让主线程在执行里面内容而已。
实现Runnable接口
-
编写自定义的 Runnable 类,实现 Runnable 接口
-
重写 run 方法,编写线程要执行的内容
-
创建自定义的 Runnable 类对象
-
创建线程对象,指定构造参数为自定义的 Runnable 类对象
-
启动线程
继承 Thread 类的方式,直接将对应线程类型未来的继承 “堵死了”,因为 Java 是单继承的。
建议采用实现 Runnable 接口方式。
线程的生命周期(面试题)
-
创建状态
创建了线程对象后
-
就绪状态
调用 start 方法后
-
运行状态
抢占到 CPU 资源后
-
阻塞状态
输入、休眠等
注意: 阻塞状态结束后,会进入就绪状态
-
死亡状态
线程自然执行完毕或外部干涉终止线程
线程的调度
线程优先级
默认的优先级是 5(NORM_PRIORITY),最小的优先级是 1(MIN_PRIORITY),最大的优先级是 10(MAX_PRIORITY)
-
setPriority(int) : void 设置优先级
-
getPriority() : int 获取优先级
优先级高的线程获得 CPU 资源的 概率较大 。
线程休眠
让线程暂时睡眠指定时长,线程会进入阻塞状态。
睡眠时间过后,线程会进入就绪状态。
-
static sleep(millis:long) : void 休眠指定毫秒时间
线程强制运行
使当前线程暂停执行,等待其他线程结束后再继续执行本线程。
-
join() : void 等待另一个线程结束才执行
-
join(millis:long) : void 等待多长时间
调用 join 方法的是要执行的线程对象,而不是当前正在运行的线程对象。
join:加入
线程礼让
暂停当前线程,允许其他具有 相同优先级 的线程获得运行机会。
该线程处于就绪状态,不转为阻塞状态。
-
static yield() : void
只是提供 一种可能,不保证一定会实现礼让。
多线程安全问题
多个线程之间有共享的数据,并且对共享数据有修改的操作,这是多线程安全问题的前置条件。
同步方法
[访问权限修饰符] synchronized 返回值类型 方法名([形参列表]) { } synchronized [访问权限修饰符] 返回值类型 方法名([形参列表]) { }
同步代码块
synchronized (同步对象) { }
在添加了 synchroized 解决线程安全问题后,效率肯定会降低。
在多线程的情况,先要解决安全问题,然后再考虑性能。
在单线程的情况,还是以考虑性能为主。