多线程
- 概念详解:
- 并行 和 并发两者的区别:
- 并发:指两个或多个事件在同一个时间段内发生(同一时间段发生)
- 并行:指两个或多个事件在同一时刻发生(同时发生)
- 线程 和 进程两者的区别:
- 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程 中是可以有多个线程的,这个应用程序也可以称之为多线程程序
- 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多 个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创 建、运行到消亡的过程。
- 总结:就是一个程序至少是包含一个进程 一个进程至少是包含一个线程
- 线程调度的方式: 两种方式
- 分时调度 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间
- 抢占式调度 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度
- 并行 和 并发两者的区别:
- 创建线程类:
- 创建线程类的方式 和 步骤:
- 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体。
- 创建Thread子类的实例,即创建了线程对象
- 调用线程对象的start()方法来启动该线程
public class Test { public static void main(String[] args) { MyThread mt = new MyThread("新的线程!"); //开启新线程 mt.start(); //在主方法中执行for循环 for (int i = 0; i < 10; i++) { System.out.println("main线程!" + i); } } } class MyThread extends Thread { //定义指定线程名称的构造方法 public MyThread(String name) { //调用父类的String参数的构造方法,指定线程的名称 super(name); } /*** 重写run方法,完成该线程执行的逻辑 */ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName() + ":正在执行!" + i); } } }
- 创建线程类的方式 和 步骤:
- 多线程的执行步骤:
- 程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建
- 随着调用mt的对象的 start方法,另外一个新的线程也启动了,这样,整个应用就在多线程下运行
- 当执行线程的任务结束了,线程自动在栈内存中释放了 当所有的执行线程都结束了 那么进程就结束
- Thread类详解:
- 构造方法:
public Thread()
:分配一个新的线程对象public Thread(String name)
:分配一个指定名字的新的线程对象public Thread(Runnable target)
:分配一个带有指定目标新的线程对象(Runnable接口还没有讲到现在这里提一下)public Thread(Runnable target,String name)
:分配一个带有指定目标新的线程对象并指定名字
- 常用的方法:
public String getName()
:获取当前线程名称public void start()
:导致此线程开始执行; Java虚拟机调用此线程的run方法public void run()
:此线程要执行的任务在此处定义代码public static void sleep(long millis)
:使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)public static Thread currentThread()
:返回对当前正在执行的线程对象的引用
- 构造方法:
- 创建线程的三种方法 和 优略势:
- 创建线程的方式:
- 继承Thread类的方式 也是最简单的方式
- 实现Runnable接口的方式
- 使用的步骤:
- 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正 的线程对象(代理模式 也就是上面的构造方法的第三种方式
public Thread(Runnable target)
) - 调用线程对象的start()方法来启动线程
- 使用的步骤:
- 实现Callable接口的方式 就是创建Callable接口的实现类 重写call方法
- 不同中方式的优略势(也就是说 既然已经有了Thread类的方式 为什么还要有Runnbale接口的方式 或者说是Runnable方式的优点)
- Runnable方式适合多个相同的程序代码的线程去共享同一个资源
- Runnable方式可以避免java中的单继承的局限性
- Runnable方式增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
- Java程序启动是最少启动的线程是:在Java程序启动中 最少启动两个线程 一个就是main线程 另一个就是垃圾回收线程 而JVM的启动实际上是一个进程的启动
- 对示例中方式的改进:使用匿名内部类的形式来进行多线程的创建
- 创建线程的方式:
- 线程安全问题:
- 什么是线程安全:简单的说就是多线程环境下代码的运行 和 在单线程的运行结果是一致的 就是线程安全的
- 线程安全问题出现的原因:线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。
- 解决线程安全问题的方式:线程同步
- 线程同步的三种方式:
-
同步代码块
synchronized
关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问synchronized(同步锁){ 需要同步操作的代码 }
- 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁. 1. 锁对象 可以是任意类型。 2. 多个线程对象 要使用同一把锁
-
同步方法 使用s
ynchronized
修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外 等着public synchronized void method(){ 可能会产生线程安全问题的代码 }
- 对于非static方法,同步锁就是this。 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
-
锁机制(一种更加面向对象的机制)
java.util.concurrent.locks.Lock
Lock锁 加锁和释放锁的方法:public void lock()
:加同步锁public void unlock()
:释放同步锁
-
- 线程同步的三种方式:
- 线程状态:线程的生命周期中有六种状态
来源:CSDN
作者:上山打小鼠
链接:https://blog.csdn.net/qq_41922608/article/details/103974003