多线程详解

    技术2025-12-24  22

    多线程详解

    并发与并行并发并行并发编程并发编程的三特性 线程与进程线程进程区别 线程的状态及状态转换线程六状态进入Terminated状态的情况 状态间的转换 线程常用方法yield和sleep的区别:

    并发与并行

    并发

    并发:多个线程操作同一个资源,不是同时执行,而是交替执行,单核CPU交替执行时间间隔特别短,

    并行

    并行:并行指的是同时执行,多核CPU,每一个线程使用一个单独CPU,

    并发编程

    并发编程:指多个任务在一个时间段重复执行的结构

    并发编程的三特性

    并发编程的三个特性: 1.原子性 原子操作:不可分割的操作,中间不会被其他线程打断,不需要同步操作 多个原子操作合起来就需要使用到同步 原子性指的是一次操作或者多个操作,要么全部执行,要么全部都不执行 例如: int a = 10 ; //原子操作 a++; // 不是原子操作 int b = a; //不是原子操作 a = a+1; // 不是操作

    2.可见性 当在一个线程中队某一共享变量进行了修改,那么另外的线程可以立即看到修改后的新值

    3.顺序性 程序代码在执行过程中的先后顺序 单线程环境指令重排序不会影响最终的结果

    如何实现高并发(提高系统的并发能力) 垂直扩展(硬件): 增强计算机的硬件性能:增加cpu核数,内存升级,磁盘扩容 提高系统的架构能力:使用cache提高效率 水平扩展(软件): 集群,分布式

    线程与进程

    线程

    线程是组成进程的基本单位,cpu调用的最小单位

    进程

    进程是计算机上的独立的应用程序,资源分配的最小单位

    区别

    1.内存空间 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。

    2.安全性 多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

    3.效率 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式进行。

    线程的状态及状态转换

    线程六状态

    1).New----Thread对象的状态,在没有start之前,该线程不存在时;

    2).Runnable----Thread对象进入Runnable状态必须调用start方法,此时真正的在JVM中创建了一个线程,线程启动之后并不会立即去执行,该状态的线程位于可运行线程池中,等待操作系统的资源,比如:处理器 (在等待cpu的使用权;

    3).Running----一旦CPU选中了线程,那么此时该线程能够去执行自己的逻辑代码;

    4).Blocked----等待一个监视器锁进入到synchronized block/method,处理这个里面的逻辑代码在某一时刻只能允许一个线程执行,其他线程只能去等待,这种情况下,等待的线程处于Blocked状态,处于Blocked状态的线程获取到了监视器锁,则应该从Blocked状态转换到Runnable状态;

    5).WAITING/TIMED_WAITING----等待状态

    6).Terminated----该状态表示线程的最终状态,在该状态中线程不会切换到其他的状态,线程进入该状态,意味着线程的整个生命周期已经结束;

    进入Terminated状态的情况

    进入Terminated状态的三种情况: 1.线程运行正常结束 2.线程运行出错 3.JVM crash,导致所有线程结束

    状态间的转换

    线程常用方法

    1.start() 开启线程

    2.sleep() Thread.sleep() 使得当前线程进入指定毫秒数的休眠 休眠有一个重要特性,不会放弃monitor锁的使用权 jdk1.5之后,引入枚举TimeUnit

    3.yield() 让步一次cpu时间片,只是对于cpu调度器的一个提示

    4.joind() 在线程A中,join某个线程B,会使得线程A进入等待,直到线程B结束了自己的生命周期或者达到给定的时间,那么在此期间,线程A处于等待状态 join方法可以使得线程顺序执行

    5.interrupt() 中断线程的方法 ----Thread.sleep() | ----Object.wait() | ----Thread.join() | ----Selector.wakeUp() | 这些为可中断方法,不和interrupt方法同时使用(调用这些方法后,线程处于阻塞状态,如果另一线程调用被阻塞线程的interrupt方法,则会打断这个线程的阻塞状态,并会报错)

    6.isInterrupted() 判断线程是否被中断

    7.interrupted() 静态方法,底层调用isInterrupted方法,检测线程是否被中断 第一次调用interrupted方法会返回true,并且会立即擦除线程中的中断状态位,之后调用都会返回false

    yield和sleep的区别:

    yield和sleep的区别: 1)sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给优先级低的线程以运行的机会,而yield()方法只会给相同优先级或者更高优先级的线程以运行机会。 2)线程执行sleep()方法后会转入阻塞状态,所以,执行sleep()方法的线程在指定的时间内肯定不会被执行,而yield()方法只是使当前线程重新回到可执行状态,所以执行yield()方法的线程有可能在进入到可执行状态后马上又被执行。 3)sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常。 4)sleep()方法比yield()方法(跟操作系统)具有更好的可移植性。

    Processed: 0.019, SQL: 9