4-java并发

文章详细介绍了线程和进程的区别,包括资源分配、开销和执行流程。讨论了线程的创建方式、状态流转以及如何避免线程死锁。此外,还涵盖了Java内存模型、volatile关键字、守护线程、可重入锁的概念。同时,文章讲解了线程池的使用好处、核心参数和执行任务的流程,以及不同类型的线程池。最后,提到了线程的阻塞情况和结束方式,以及synchronized和volatile、锁机制的相关知识。
摘要由CSDN通过智能技术生成

1_线程和进程的区别?

  • 根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
  • 资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同进程的线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
  • 包含关系:进程包含线程,一个进程至少有一个线程
    内存分配:同一进程的不同线程可以共享本进程的地址空间和资源,而进程之间的地址空间和资源是独立的
  • 影响关系:一个进程崩溃不会影响其他进程,一个线程崩溃整个进程都要死掉
  • 执行过程:每个独立的进程有程序运行的入口.顺序执行序列和程序出口。但是线程不能独立执行,必 须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

创建线程的3种方式? -书栈

  1. 继承thread,重写run()方法
  2. 实现runnable接口,重写run()方法,生成一个实例,在创建Thread的时候传入这个实例
  3. 实现callable接口,重写call()方法,生成一个实例,在创建Thread的时候传入这个实例

3_线程的状态流转?

new(新建):当线程对象被创建后,即进入了新建状态.
runnable(就绪):当调用线程对象的start()方法,线程即进入就绪状态。
running(运行):当线程开始调度处于就绪状态的线程时,进入运行状态。
block(阻塞):处于运行状态中的线程由于某种原因,暂时放弃对cpu的使用权,停止执行,此时进入阻塞状态.
dead(死亡):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

5_什么是线程死锁,如何避免死锁?- 书栈

java内存模型

在Java虚拟机中,变量的值保存在主内存中,但是,当线程访问变量时,它会先获取一个副本,并保存在自己的工作内存中。如果线程修改了变量的值,虚拟机会在某个时刻把修改后的值回写到主内存,但是,这个时间是不确定的!

volatile

每次访问变量时,总是获取主内存的最新值;
每次修改变量后,立刻回写到主内存。

daemon Thread

守护线程是指为其他线程服务的线程。在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。守护线程不能持有需要关闭的资源(如打开文件等)。

可重入锁

JVM允许同一个线程重复获取同一个锁,这种能被同一个线程反复获取的锁,就叫做可重入锁。

什么是线程死锁

两个线程各自持有不同的锁,然后各自试图获取对方手里的锁,造成了双方无限等待下去,这就是死锁

如何避免死锁

线程获取锁的顺序要一致

6_Runnable 和 Callable 对比

  • Callable 规定(重写)的方法是call()方法, runnable 规定(重写)的方法是run()方法。
  • call()方法有返回值,而run()方法没有返回值。
  • call()方法可以抛出异常,run()方法不可以。

6_shutdown 和 shutdownNow

shutdown():方法关闭线程池的时候,它会等待正在执行的任务先完成,然后再关闭。
shutdownNow(): 会立刻停止正在执行的任务。
awaitTermination():会等待指定的时间让线程池关闭。

7_sleep 和 wait

相同

两者都会使线程进入阻塞状态

不同

  • sleep 方法是Thread类的静态方法,当前线程将睡眠n毫秒,线程进入阻塞状态,当睡眠时间到了,会解除阻塞,进入可运行状态。如果有的话,睡眠不释放锁。
  • wait 方法是Object的方法,必须与synchronized关键字一起使用,线程进入阻塞状态,当notify 或者notifyAll被调用后,会解除阻塞。但是,只有重新持有互斥锁之后才会进入可运行状态。等待时,会释放互斥锁。

8_为什么我们调用start()方法时会调用run()方法,为什么我们不能直接调用run()方法

  • new 一个 Thread线程进入了new状态; 调用start 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,(调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。)这是真正的多线程工作。
  • 直接执行run 方法,并不会开启新的线程中执行它。

12_线程阻塞的三种情况

  1. 等待阻塞, running状态下的线程,执行wait方法后,jvm会将线程放入等待队列(wait queue)。
  2. 同步阻塞, running状态下的线程,在获取对象的同步锁时,若同步锁被其他的线程占用,则JVM将该线程放入锁池(lock pool)中。
  3. 其他阻塞, running状态下的线程, 执行sleep或者join方法,或发出I/O请求时,JVM会将该线程设置为阻塞状态。当sleep超时,join等待线程终止超时,或I/O处理完毕时,线程重新转入可运行状态。

13_线程死亡的三种方式

  1. 正常结束, run、call方法执行完毕,线程正常结束。
  2. 异常结束, 线程抛出一个未捕获的exception 或 error,导致线程异常结束。
  3. 调用stop结束,一般不推荐这样使用,因为有可能会导致死锁。

19_synchronized 和 volatile 的区别是什么?

  1. volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读 取; synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile 仅能使用在变量级别 ; synchronized 则可以使用在 变量、方法、类级别。
  3. volatile 仅能实现变量的修改可见性,不能保证原子性; 而 synchronized 则可以保证变量的修改可见性和原子性。
  4. volatile 不会造成线程的阻塞 ; synchronized 可能造成线程的阻塞。
  5. volatile 标记的变量不会被编译器优化; synchronized 标记的变量可以被编译器优化。

20_synchronized 和 lock 的区别是什么?

  1. synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
  2. synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁; 而 lock 需要自己加锁和释放锁,如果使用不当没有 unlock() 去释放锁就会造成死锁。
  3. 通过 lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

21_synchronized 和 ReentrantLock 的区别是什么?

  1. 两者都是可重入锁
    可重入锁:重入锁,也叫做递归锁,可重入锁指的是在一个线程中可以多次获取同一把锁,比如: 一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行 调用的方法,而无需重新获得锁, 两者都是同一个线程每进入一次,锁的计数器都自增􏰀,所以要等到锁的计数器下降为􏰹时才能释放锁。

  2. synchronized 依赖与JVM 而 ReentrantLock 依赖与API
    synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团队在 jdk1.6 为 synchronized 关 键字进行了很多优化,但是这些优化都是在虚拟机层面实现的
    ReentrantLock 是 jdk 层面实现的(也就是 api 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成)

  3. ReentrantLock 比 synchronized 增加了一些高级功能

主要来说主要有三点:1等待可中断;2可 实现公平锁;3可实现选择性通知(锁可以绑定多个条件)

  • 等待可中断,通过 lock.lockInterruptibly() 来实现这个机制。也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
  • ReentrantLock 可以指定是公平锁还是非公平锁。而 synchronized 只能是非公平锁。所谓的公平锁 就是先等待的线程先获得锁。 ReentrantLock 默认情况是非公平的,可以通过 ReentrantLock 类的 ReentrantLock(boolen fair) 构造方法来制定是否是公平的。
  • ReentrantLock 类线程对象可以注册在指定的 Condition 中,从而可以有选择性的进行线程通知,在 调度线程上更加灵活。 在使用 signal/signalAll 方法进行通知时,被通知的线程是由 JVM 选择 的,使用 ReentrantLock类结合Condition实例可以实现“选择性通知”。
  1. 选择使用

除非需要使用 ReentrantLock 的高级功能,否则优先使用 synchronized。

26_synchronized为什么是非公平锁?非公平锁体现在哪些地方?

synchronized 的非公平其实在源码中应该有不少地方,因为设计者就没按公平锁来设计,核心有以下几 个点:

  1. 当持有锁的线程释放锁时,该线程会执行以下两个重要操作:
  • 先将锁的持有者 owner 属性赋值为 null
  • 唤醒等待链表中的一个线程(假定继承者)。
    在唤醒等待线程的时候,如果有其他线程刚好在尝试获取锁(例如自旋),则可以马上获取到锁。
  1. 当线程尝试获取锁失败,进入阻塞时,放入链表的顺序,和最终被唤醒的顺序是不一致的,也就是说 你先进入链表,不代表你就会先被唤醒。

32_了解 reentrantLock 吗?

reentrantLock 是一个可重入的独占锁,主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入。
reentrantLock 实现依赖于 AQS
reentrantLock 主要依靠AQS维护一个阻塞队列,多个线程对加锁时,失败则会进入阻塞队列(锁池?)。等待唤醒,重新尝试获取锁。

33_ReadWriteLock是什么?

首先 reentrantLock 某些时候有局限,如果使用 reentrantLock 可能本身是为了防止线程A在写数据、 线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。
因为这个,才诞生了读写锁 ReadWriteLock ReadWriteLock 是一个读写锁接口, ReentrantReadWriteLock 是 ReadWriteLock 接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能

线程池_1_为什么使用线程池

使用线程池的好处:

  1. 降低资源消耗,通过重复利用已经创建的线程来降低线程创建和销毁造成的消耗。
  2. 提高响应速度,当任务到达时,任务可以不需要等待线程创建而直接执行。
  3. 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统稳定性。使用线程池可以进行统一的分配,调优和监控。

线程池_2_执行excute和submit方法的区别是什么

  • excute() 方法用于提交不需要返回值的任务。
  • submit() 方法用于提交需要返回值的任务。

线程池_3_说一下线程池核心参数

  • 核心线程数/corePoorSize, 线程池一直运行,核心线程就不会停止
  • 最大线程数/maxPoorSize
  • 非核心线程的心跳时间/keepAliveTime, 如果非核心现在在心跳时间内没有任务执行,非核心线程就会消亡。
  • 阻塞队列/workQueue, 用来存放线程任务
  • 饱和策略/defaultHandler,4种
    1. 线程任务丢弃报错。默认饱和策略
    2. 线程任务直接丢弃不报错。
    3. 将阻塞队列首任务丢弃,将最新线程任务重新加入队列执行。
    4. 线程池之外的线程直接调用run方法执行。
  • 线程工厂/ThreadFactory

线程池执行任务的流程

要执行的任务数< 核心线程数,则不会进入队列,而是创建新的线程

要执行的任务数 > 核心线程数,并且等待队列未满,则进入等待队列;

要执行的任务数 > 核心线程数,并且 < 最大连接数 并且 等待队列已满,则创建新线程;

要执行的任务数 > 核心线程数,并且 > 最大连接数 并且 等待队列已满,则调用拒绝策略来处理该任务(抛异常)

线程池_5_常见的java线程池有哪几种

FixedThreadPool:线程数固定的线程池;
CachedThreadPool:线程数根据任务动态调整的线程池;
SingleThreadExecutor:仅单线程执行的线程池。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值