目录·
一、并发和并行
- 并发:指两个或多个事件在同一个时间段内发生。
- 并行:指两个或多个事件在同一时刻发生(同时发生)。
二、进程和线程
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位。
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
三、线程调度
分时调度:所有线程轮流使用CPU,平均分配每个线程占用CPU的时间。
抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
四、创建线程
Java17
Thread类地址:java.lang.Thread
There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread.The other way to create a thread is to declare a class that implements the Runnable interface. That class then implements the run method.
4.1 实现方案一:继承Thread类
- 定义一个子类 MyThread 继承线程类 java.lang.Thread,重写 run() 方法
- 创建 MyThread 类的对象
- 调用线程对象的 start() 方法启动线程(启动后还是执行 run 方法的)
package com.wangpeng;
/**
* 多线程的创建方式一:继承Thread类 重写run方法
*/
public class ThreadDemo {
public static void main(String[] args) {
// 1.创建子线程对象
Thread myThread = new MyThread();
// 2.调用start方法启动线程
myThread.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行输出" + i);
}
}
}
class MyThread extends Thread{
/**
* 重写run方法,里面定义子线程需要做什么。
*/
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程执行输出:" + i);
}
}
}
4.2 实现方案二:实现Runnable接口
- 定义一个线程任务类 MyRunnable 实现 Runnable 接口,重写 run()方法
- 创建 MyRunnable 对象
- 把 MyRunnable 任务对象交给 Thread 处理
- 调用线程对象的 start() 方法启动线程
package com.wangpeng;
/**
* 多线程的创建方式二:实现Runnable接口,并重写其run方法
*/
public class DemoThreadTwo {
public static void main(String[] args) {
// 1. 创建一个MyRunnable对象
Runnable myRunnable = new MyRunnable();
// 2.把MyRunnable对象交给进程处理
Thread thread = new Thread(myRunnable);
// 3.启动线程
thread.start();
for (int i = 0; i < 8; i++) {
System.out.println("主线程执行输出:" + i);
}
}
}
class MyRunnable implements Runnable{
// 重写run方法,定义线程执行任务
@Override
public void run() {
for (int i = 0; i < 8; i++) {
System.out.println("子线程执行输出:" + i);
}
}
}
五、线程常用方法
获取线程名称及设置线程名称
package com.wangpeng;
public class DemoThreadThree {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " :" + i);
}
Thread t1 = new MyThreadOne();
t1.setName("线程一");
t1.start();
Thread t2 = new MyThreadOne();
t2.setName("线程二");
t2.start();
}
}
class MyThreadOne extends Thread{
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " :" + i);
}
}
}
main :0
main :1
main :2
线程二 :0
线程一 :0
线程二 :1
线程一 :1
线程二 :2
线程一 :2
Thread类的线程休眠方法
六、线程安全问题
- 多个线程同时操作同一个共享资源的时候可能出现业务安全问题,称为线程安全问题。
七、线程同步
加锁:把共享资源进行上锁,每次只能一个线程进入,访问完毕后以后解锁,然后其他线程才能进来。
同步代码块
- 作用:把出现线程安全问题的核心代码给上锁。
- 原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行。
同步方法
- 作用:把出现线程安全问题的核心方法给上锁。
- 原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行。
- 取钱案例
one来取钱了,吐出100000.0 账户余额还剩0.0
two来取钱了,余额不足!
锁对象的规范要求:
- 规范上:建议使用共享资源作为锁对象
- 对于实例方法建议使用this作为锁对象
- 对于静态方法建议使用字节码(类名.class)对象作为锁对象
本文含有隐藏内容,请 开通VIP 后查看