多线程概念总结

本文概述了进程与线程的概念,强调了它们的区别,介绍了线程调度的分时与抢占式策略,讨论了线程同步与异步,讲解了Runnable接口的使用和守护线程的作用,以及线程安全问题和线程状态。最后,涵盖了线程池的种类及其应用场景。
摘要由CSDN通过智能技术生成

进程与线程

    进程

  • 指的是一个内存中运行的应用程序,每个进程都有一个独立内存空间
  • 当一个程序一个线程都没有了的时候,程序结束

    线程

  • 是进程中的一个执行路径执行任务,线程之间可以互相切换,并发执行,一个进程最少有一个线程
  • 同类的多个线程共享进程的堆和方法区的资源,每个线程有自己的程序计数器,虚拟机栈和本地方法栈,线程之间切换开销较小
  • 线程是进程的进一步划分,一个进程在启动后有多个执行路径,里面的若干执行路径可划分为若干个线程

    为什么程序计数器是线程私有的?

  • 字节码解释器是通过程序技术器来按顺序执行指令,实现代码的流程控制-顺序执行,选择,循环,异常处理
  • 多线程的情况下,程序计数器用于记录当前线程的执行位置,当本线程重新得到时间偏可以根据之前的记录继续执行程序
  • 注意:执行的如果执行native方法,程序计数器记录的是undefined地址,只有执行Java代码的时候程序计数器才会记录下一条指令的地址

    虚拟机栈&本地方法栈为私有

  • 虚拟机栈:Java方法在执行的时候回创建一个栈帧用于储存局部变量表,操作数栈,常量池引用信息等。从方法调用至执行完成过程,对应着一个栈帧在Java虚拟机中入栈和出栈的过程
  • 本地方法:与虚拟机栈作用类似,区别在于:虚拟机栈储存的是Java方法(字节码)执行时产生的信息,本地方法栈则为虚拟机使用到的native方法服务

    结论:为了保证线程中的局部变量不被别的线程访问到,虚拟机和本地方法栈是线程私有

线程的调度

    分时调度

  • 平均分配每个线程使用CPU的时间,所有线程平均分配CPU的使用权

    抢占式调度

  • 优先级高的线程比低的线程占有CPU的概率高,如果优先级相同那么则会随机选择一个线程
  • CPU切换线程也会消耗时间,一个CPU同时处理1000个进程,比1000个进程排序执行效率要低
  • CPU的一个核心在同时只能执行一个线程,多个线程在该核心上来回切换看上去像是在同一时刻运行,多线程程序不能上程序执行的更快,但是可以提高程序运行的效率,提高CPU的使用率

线程的同步与异步

  • 同步:排队执行,效率低但是安全
  • 异步:多个线程所使用的资源可能会产生冲突,效率高

并发与并行

  • 并发:同一时间段内,发生的一件或多件事情的场景。场景中往往有公用资源,容易针对这个公共资源产生瓶颈
  • 并行:两个或多个事情同时正在发生,同时被处理,是真正的同时

实现Runnable

    实现Runnable与继承Thread相比的优势:

  • 通过创建任务然后将任务分配给线程的方式实现多线程,更加适合多个线程同时执行相同任务的情况
  • 可以避免单继承所里带来的局限性
  • 任务与线程分离,提高了程序的健壮性
  • 线程池,接受Runnable,不接受Thread类型

守护线程

    线程分守护线程和用户线程,当一个进程不包含任何的存活的用户线程时,进程结束。守护线程守护用户线程,当最后的用户线程结束时所有守护线程自动死亡

线程安全问题

  • 隐式锁:同步代码块 + 同步方法,只要把关键语句和格式写好方法会自己锁自己解开
  • 显示锁:自己锁,自己解开

    隐式锁和显示锁的区别:

  1. 底层实现的不同

    Sync:是Java中的关键字,由JVM来维护,是虚拟机层面上的锁
    Lock:是一个具体的类,JDK5开始出现。通过Lock调用API来实现,是API层面的锁

        Sync是在底层通过monitorenter进行上锁,通过Monitor对象来完成,使用wait和notify方法这是依赖于monitor对象。只有在同步代码块和同步方法中才能调用wait和notify等方法,原因是只有在以上两种情况里JVM才会调用Monitor对象,通过monitorExit来退出锁。
        Lock是通过调用对应的API方法来获取和释放锁的。
        从编译后的汇编语句也可以看到Lock和Sync的区别。

  2. 使用方法的不同

        Sync为隐式,Lock是显式。二者区别在于是否需要程序员动手去写相关代码来获取锁和释放锁。
        Sync代码块执行完毕后,程序会自动释放所占用的锁,由系统维护,如果不是出了逻辑的问题不会出现死锁。
        Lock需要程序员手动获取和释放,如果不释放锁可能会出现死锁:lock.lock( ), lock.unlock( )。配合try/finaly语句来完成

  3. 等待是否可以中断

        Sync是不能中断的。除非抛出异常或者正常运行完毕
        Lock是可以中断的,主要是一下两种方式:

    • 调用设置超时方法:tryLock(long timeout, timeUnit unit)
    • 调用lockInterruptibly() 放在代码块中,调用interrupt()方法可以中断

线程的状态

new:线程刚刚被创建,尚未启动
Runnable:在Java虚拟机中执行的线程处于此状态
Blocked:被阻塞等待监视器锁定的线程处于此状态
Waiting:无限期等待另一个线程执行特定操作的线程
Timed Waiting:正在等待另一个线程执行最多指定等待时间的操作的线程
Terminated:线程死亡

在这里插入图片描述
    线程在Running的过程中会遇到阻塞(Blocked)的集中情况

  1. 调用join()和sleep()方法,sleep()时间结束,join()中断,以上情况IO完成都会回到Runnable的状态,等待JVM的调度
  2. 调用wait(),将该线程放置到等待线程池(wait blocked
    pool),直到被notify()/notifyAll(),线程被唤醒放置到锁定池(lock blocked pool),
    释放同步锁线程回到Runnable
  3. 直接对线程加入同步锁(Synchronized),将线程加入到(lock blocked pool),同步锁被释放进入Runnable

线程池

  • 缓存线程池
    长度无限,判断线程池是否有空闲线程,存在则使用,不存在创建线程放入线程池然后使用。
  • 定长线程池
    与缓存线程池相似,但是有固定长度。
  • 单线程线程池
    只有一个线程的线程池

引用链接

    [1]: https://blog.csdn.net/ThinkWon/article/details/102021274
    [2]: https://blog.csdn.net/kaizi_1992/article/details/105550689

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值