Java --多线程
一、进程与线程的概念
- 进程:是操作系统进行资源分配和调度的基本单位,本质是程序的一次运行实例,拥有独立的内存空间和系统资源。
- 线程:是进程的执行单元,也是 CPU 调度和执行的基本单位,一个进程可以包含多个线程,线程之间会共享所属进程的内存资源。
二、多进程与多线程的理解
- 多进程 指操作系统能同时运行多个进程,进程之间相互独立,不会共享资源,进程间的通信需要借助管道、套接字等专门的进程间通信机制。其优点是稳定性高,一个进程崩溃不会影响其他进程的运行;缺点是资源消耗大,进程之间切换的开销较高。
- 多线程 指一个进程内部同时运行多个线程,线程会共享进程的堆、方法区等资源,同时每个线程也拥有私有的程序计数器、虚拟机栈和本地方法栈。其优点是资源消耗小,线程切换的开销低,线程间的通信也更加便捷;缺点是线程安全问题突出,一个线程崩溃可能会导致整个进程终止。
三、自定义线程类的两种方式
方式 1:继承 Thread 类 - 定义一个类,直接继承 java.lang.Thread 类。
2.重写 Thread 类中的 run 方法,在方法中编写线程需要执行的业务逻辑。 - 创建该自定义线程类的对象,调用 start 方法启动线程。需要注意的是,直接调用 run 方法只是普通的方法调用,并不会启动新的线程。
方式 2:实现 Runnable 接口
1.定义一个类,实现 java.lang.Runnable 接口
2.重写 Runnable 接口中的 run 方法,编写线程的执行逻辑。
3. 创建该 Runnable 实现类的对象,将其作为参数传入 Thread 类的构造器,创建 Thread 类的对象。
4. 调用 Thread 对象的 start 方法启动线程。
两种方式的特点
继承 Thread 类的方式编程较为简单,但受限于 Java 的单继承机制,该自定义类无法再继承其他类;实现 Runnable 接口的方式可以避免单继承的限制,同时更便于实现多个线程共享同一个资源,是更推荐使用的方式。
四、多线程的实现与线程同步
1.多线程的启动与状态
多线程的启动必须调用 Thread 类的 start 方法,调用后线程会进入就绪态,等待 CPU 调度后才能进入运行态执行 run 方法中的逻辑。线程的完整生命周期包含新建态、就绪态、运行态、阻塞态和终止态,线程会在这些状态之间根据执行情况进行转换。
2. 线程安全问题
当多个线程同时操作同一个共享资源时,就会出现数据错乱等线程安全问题,比如多个线程同时对一个变量进行自增操作,可能会得到错误的结果。
3. 线程同步的实现方式
方式 1:同步代码块
使用 synchronized 关键字修饰一段代码块,语法格式为synchronized(同步锁对象) { 需要同步的代码 }。同步锁对象的选择有一定要求:在实例方法中,通常使用 this 作为锁对象;在静态方法中,通常使用类的字节码对象作为锁对象;并且多个线程必须使用同一个锁对象,否则同步机制会失效。同步代码块可以保证同一时间只有一个线程能执行代码块中的内容,从而解决线程安全问题。
方式 2:同步方法
使用 synchronized 关键字修饰整个方法,被修饰的方法即为同步方法。同步方法的锁对象是固定的:实例同步方法的锁对象是 this,静态同步方法的锁对象是类的字节码对象。同步方法同样能保证同一时间只有一个线程执行方法内的逻辑。
方式 3:Lock 锁
这是 JDK 5 新增的同步方式,Lock 是一个接口,常用的实现类是 ReentrantLock。使用时需要先创建 Lock 接口的实现类对象,在需要同步的代码执行前调用 lock 方法加锁,在代码执行完成后调用 unlock 方法释放锁。为了避免出现死锁问题,释放锁的操作通常要放在 finally 代码块中。相比于 synchronized 关键字,Lock 锁的使用更加灵活。
4. 同步方式的特点
synchronized 关键字的语法较为简单,灵活性较低,锁的释放是自动的,当同步代码块或同步方法执行完毕,或者出现异常时,会自动释放锁;Lock 锁的语法稍复杂,但是灵活性更高,锁的获取和释放都需要手动通过方法调用实现。
更多推荐


所有评论(0)