JUC-线程基础篇

1.创建线程的3种方式

继承Thread类

实现Runnable接口

实现Callable接口

2.线程的5种状态

初始、就绪、运行、阻塞、死亡

3.线程的相关API

sleep会让当前线程从 Running 进入 Timed Waiting 状态(阻塞),不会释放对象锁

yield会释放CPU资源,让当前线程从 Running 进入 Runnable就绪状态,让优先级更高(至少是相同)的线程获得执行机会,不会释放对象锁

join,方法用于让当前线程等待另一个线程执行完毕。一般用于等待异步线程执行完结果之后才能继续运行的场景

wait释放锁因为wait前先获取到锁,通过notify唤醒时候,notify的线程也要加锁,如果wait不释放锁,notify就拿不到锁,也无法唤醒wait的线程

notify():通知一个在对象上等待的线程,使其从wait方法返回,而返回的前提是该线程获取到了对象的锁,没有获得锁的线程重新进入WAITING状态。

notifyAll():通知所有等待在该对象上的线程。尽可能用notifyAll(),谨慎使用notify(),因为notify()只会唤醒一个线程,我们无法确保被唤醒的这个线程一定就是我们需要唤醒的线程。

4.线程的优先级

线程优先级会提示调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它。如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用。

在Java线程中,通过一个整型成员变量priority来控制优先级,优先级的范围从1~10,在线程构建的时候可以通过setPriority(int)方法来修改优先级,默认优先级是5,优先级高的线程分配时间片的数量要多于优先级低的线程。

在不同的JVM以及操作系统上,线程规划会存在差异,有些操作系统甚至会忽略对线程优先级的设定。

5.守护线程

默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了即使守护线程的代码没有执行完,也会强制结束

6.守护线程的应用场景

JVM中垃圾回收器就采用了守护线程,如果一个程序中没有任何用户线程,那么就不会产生垃圾,垃圾回收器也就不需要工作了。

7.线程的终止

不要使用stop方法。stop()方法已经被jdk废弃,调用stop方法无论run()中的逻辑是否执行完,都会释放CPU资源,释放锁资源,会释放当前线程所持有的所有的锁。这会导致线程不安全。

isInterrupted(),判断是否被中断,不会清除 中断标记

interrupted(),判断当前线程是否被中断 ,会清除中断标记

interrupt(),中断线程,如果被中断线程正在 sleep,wait,join 会导致被中断的线程抛出 InterruptedException,并清除 中断标记 ;如果中断的正在运行的线程,则会设置中断标记 ;park 的线程被中断,也会设置中断标记

8.中断机制

安全的中止则是其他线程通过调用某个线程A的interrupt()方法对其进行中断操作, 中断好比其他线程对该线程打了个招呼,“A,你要中断了”,不代表线程A会立即停止自己的工作,同样的A线程完全可以不理会这种中断请求。线程通过检查自身的中断标志位是否被置为true来进行响应

注意:处于死锁状态的线程无法被中断

9.volatile关键字

volatile保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

volatile最适用的场景:一个线程写,多个线程读

根据JMM的规定,线程对共享变量的所有操作都必须在自己的本地内存中进行,不能直接从主内存中读取

10.LockSupport

LockSupport是JDK中用来实现线程阻塞和唤醒的工具,线程调用park等待“许可”,调用unpark则为指定线程提供“许可”

如果这个许可还没有被占用,当前线程获取许可并继续执行;如果许可已经被占用,当前线程阻塞,等待获取许可。

Java锁和同步器框架的核心AQS,是通过调用LockSupport.park()和LockSupport.unpark()实现线程的阻塞和唤醒的。

park(),当没有『许可』时,当前线程暂停运行;有『许可』时,用掉这个『许可』,当前线程恢复运行。

LockSupport允许先调用unpark(Thread t),后调用park()。如果thread1先调用unpark(thread2) - 发放许可,然后线程2后调用park(),线程2是不会阻塞的。如果线程1先调用notify,然后线程2再调用wait的话,线程2是会被阻塞的。

LockSupport.park()和unpark()随时随地都可以调用。而wait和notify只能在synchronized代码段中调用

11.LockSupport和synchronized区别

synchronized 关键字:

自动管理锁的获取和释放。

当异常发生时,锁会被自动释放,从而避免了死锁的风险。

在 Java 6 之后进行了许多优化,例如偏向锁、轻量级锁和重量级锁等,以提高性能。

LockSupport 类:

主要用于实现更复杂的同步结构,而不是直接用于同步代码块。

如果线程被中断,LockSupport.park() 方法会立即返回,但不会抛出 InterruptedException。

通常与其他同步工具(如 Condition)一起使用。

总结:

在大多数情况下,对于一般的同步需求,synchronized 和 ReentrantLock(或其他 Lock 实现)会是更合适的选择。LockSupport 更适合于那些需要构建自定义同步逻辑的场景。

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值