目录
进程和线程
- 进程:是正在运行的程序,是系统进行资源分配和调用的独立单位
- 线程:是进程中的一条执行路径
- 单线程:一个进程只有一条执行路径
- 多线程:一个进程有多条执行路径
为什么要引入多线程呢?
Java是支持多线程的,引入多线程可以提高CPU的利用率
如何实现多线程
实现多线程有三种方式
继承Thread实现多线程
- 编写一个类继承Thread类
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
注意:在单核CPU中,线程是交替运行的,由CPU进行调度
实现Runnable接口实现多线程
- 编写一个类实现Runnable接口
- 重写run()方法
Thread和Runnable的使用场景
- Runnable适合多个相同程序的代码去处理同一个资料的情况
public class MyThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
public class MyThreadTest {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"高铁");
Thread t2 = new Thread(mt,"飞机");
t1.start();
t2.start();
}
}
线程安全问题出现的条件
- 多线程环境
- 多线程共享数据
- 有多条语句操作共享数据
同步代码块解决线程安全问题
synchronized(任意对象) {
多条语句操作共享数据的代码
}
同步方法:
修饰符 synchronized 返回值类型 方法名(方法参数) {
方法体;
}
同步方法的锁对象是this
静态同步方法:
修饰符 static synchronized 返回值类型 方法名(方法参数) {
方法体;
}
同步静态方法的锁对象是 类名.class
Lock锁
虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了 锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。
Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
- ReentrantLock() 创建一个ReentrantLock的实例
- void lock() 获得锁
- void unlock() 释放锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyThread implements Runnable {
private Lock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();//上锁
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
lock.unlock();//释放锁
}
}
}
public class MyThreadTest {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"高铁");
Thread t2 = new Thread(mt,"飞机");
t1.start();
t2.start();
}
}
线程中run()和start()的区别
- void run():在run方法中编写线程体,在线程开启后,该方法将会被调用执行
- void start():开启线程,然后Java虚拟机调用run()方法
守护线程和用户线程的区别
https://blog.csdn.net/qq_43391464/article/details/111144088
生产者模式和消费者模式
https://www.cnblogs.com/luego/p/12048857.html
多线程的应用场景
待更……