JAVA juc相关

 线程的五个状态

  • 新建状态:线程已经创建,还没有在其上调用start( )方法。
  • 就绪状态:也称可运行状态,当线程调用start方法,但是线程调度程序还没有把他选定为运行线程时线程所处的状态。这时线程调用了start( )方法,但是该线程的run( )方法还没有轮到被线程调度程序调用。这种状态的线程都在可运行池中。
  • 运行状态:线程调用程序从运行池中选择一个线程作为当前线程时线程所处的状态,这也是线程进入运行状态的唯一方式。如果一个线程想要运行,只能从可运行状态变为运行状态。这种状态的线程是正在执行run( )方法。
  • 阻塞状态:线程仍然是活的,但是当前没有条件运行。当等待事件出现之后它可以返回到可运行状态,等待事件通常是等待获取除调度执行需要的CPU之外的其他系统资源。这种状态的线程正处于睡眠状态,等待其他线程首先调度执行状态等。
  • 死亡状态:当线程的run( )方法执行完毕线程就会进入死亡状态。线程一旦死去,就不能复生。

java中BLOCKED和WAITING线程状态有什么区别?

1. BLOCKED(阻塞状态):
含义: 线程在等待获取监视器锁(synchronized 锁)时,如果锁被其他线程占用,就会进入 BLOCKED 状态。
情景: 当一个线程试图访问一个被其他线程持有的对象锁时,它会被阻塞,直到获取到该锁。
出现原因: 可能是由于同步块或同步方法的进入条件不满足,导致线程在等待锁的过程中进入 BLOCKED 状态。
2. WAITING(等待状态):
含义: 线程在等待其他线程显式地通知或中断时,会进入 WAITING 状态。
情景: 当线程调用 Object.wait()、Thread.join() 或类似的方法时,线程会进入 WAITING 状态,等待其他线程的通知。
出现原因: 线程调用了等待相关的方法,进入等待状态,直到其他线程调用相应的通知方法。
总结:
BLOCKED 状态表示线程在等待获取监视器锁,它可能是由于同步块或同步方法的争用导致的。
WAITING 状态表示线程在等待其他线程的通知或中断,它可能是由于调用了 wait()、join() 等方法导致的。
这两种状态都属于线程的阻塞状态,但产生的原因和等待的条件是不同的。BLOCKED 状态是由于争夺锁而导致的,而 WAITING 状态是由于线程主动等待的情况。                   
原文链接:https://blog.csdn.net/u013718071/article/details/134888911

AQS

synchronize ReentrantLock lock 辨析

① synchronized 是JVM层面的锁,ReentrantLock 是JUC包中API层面的锁

  • synchronized是Java关键字,通过monitor对象来完成,对象只有在同步块或同步方法中才能调用wait/notify方法。
  • ReentrantLock 是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁。
  • synchronized 的实现涉及到锁的升级,具体为无锁、偏向锁、自旋锁、向OS申请重量级锁。
  • ReentrantLock实现则是通过利用CAS(CompareAndSwap)自旋机制保证线程操作的原子性和volatile保证数据可见性以实现锁的功能。

② 是否可手动释放:

  • synchronized 不需要用户去手动释放锁,synchronized 代码执行完后系统会自动让线程释放对锁的占用。
  • ReentrantLock则需要用户去手动释放锁,如果没有手动释放锁,就可能导致死锁现象。一般通过lock()和unlock()方法配合try/finally语句块来完成,使用释放更加灵活

③ 是否可中断

  • synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成;
  • ReentrantLock则可以中断,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中,调用interrupt方法进行中断

④ 是否公平锁

  • synchronized为非公平锁
  • ReentrantLock则即可以选公平锁也可以选非公平锁,通过构造方法new ReentrantLock时传入boolean值进行选择,默认false非公平锁,true为公平锁。

⑤ 锁是否可绑定条件Condition

  • synchronized不能绑定,通过Object类的wait()/notify()/notifyAll()方法要么随机唤醒一个线程要么唤醒全部线程。
  • ReentrantLock通过绑定Condition结合await()/singal()方法实现线程的精确唤醒。

 synchronized与Lock两者区别:

  1:Lock是一个接口,而Synchronized是关键字。

  2:Synchronized会自动释放锁,而Lock必须手动释放锁。

  3:Lock可以让等待锁的线程响应中断,而Synchronized不会,线程会一直等待下去。

  4:通过Lock可以知道线程有没有拿到锁,而Synchronized不能。

  5:Lock能提高多个线程读操作的效率。

  6:Synchronized能锁住类、方法和代码块,而Lock是块范围内的

synchronized底层原理

ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?

1. 什么是ArrayBlockingQueue和LinkedBlockingQueue?
ArrayBlockingQueue:是一个基于数组实现的有界阻塞队列,它按照先进先出(FIFO)的原则对元素进行排序。

LinkedBlockingQueue:是一个基于链表实现的可选有界或无界阻塞队列,它也按照先进先出(FIFO)的原则对元素进行排序。

2. 为什么需要ArrayBlockingQueue和LinkedBlockingQueue?
在多线程编程中,我们经常需要使用队列来实现线程间的数据共享。而阻塞队列是一种特殊的队列,当队列为空时,从队列中获取元素的操作会被阻塞;当队列满时,往队列中添加元素的操作会被阻塞。这样可以有效地控制线程之间的协作和同步。

ArrayBlockingQueue和LinkedBlockingQueue都是Java并发包提供的线程安全的阻塞队列实现,它们提供了不同的特性和适用场景。

3. ArrayBlockingQueue和LinkedBlockingQueue的实现原理?
ArrayBlockingQueue
ArrayBlockingQueue内部使用一个定长数组来存储元素,通过两个指针分别指向队头和队尾。

当往队列中添加元素时,如果队列已满,则添加操作会被阻塞,直到有空闲位置。

当从队列中获取元素时,如果队列为空,则获取操作会被阻塞,直到有可用元素。

ArrayBlockingQueue使用ReentrantLock来保证线程安全,并通过Condition实现阻塞和唤醒机制。

LinkedBlockingQueue
LinkedBlockingQueue内部使用一个链表来存储元素,每个节点包含一个元素和指向下一个节点的引用。

当往队列中添加元素时,如果队列已满(对于有界队列),则添加操作会被阻塞,直到有空闲位置。

当从队列中获取元素时,如果队列为空,则获取操作会被阻塞,直到有可用元素。

LinkedBlockingQueue使用两把锁分别控制队头和队尾的访问,以提高并发性能。

5. ArrayBlockingQueue和LinkedBlockingQueue的优点
ArrayBlockingQueue:

内部使用数组实现,读写性能较高。

支持有界队列,可以限制队列的大小。

LinkedBlockingQueue:

内部使用链表实现,插入和删除性能较高。

支持可选的有界或无界队列。

6. ArrayBlockingQueue和LinkedBlockingQueue的缺点
ArrayBlockingQueue:

容量固定,不支持动态扩容。

在并发情况下,可能存在线程饥饿问题(某些线程一直无法获取到锁)。

LinkedBlockingQueue:

内存消耗较大,因为每个节点都需要额外的空间来存储引用。

在并发情况下,可能存在线程饥饿问题(某些线程一直无法获取到锁)。

7. ArrayBlockingQueue和LinkedBlockingQueue的使用注意事项
ArrayBlockingQueue:

需要指定队列的容量大小。

当队列已满时,添加操作会被阻塞。

当队列为空时,获取操作会被阻塞。

LinkedBlockingQueue:

可以选择有界或无界队列。

当队列已满时(对于有界队列),添加操作会被阻塞。

当队列为空时,获取操作会被阻塞。

8. 总结
ArrayBlockingQueue和LinkedBlockingQueue是Java并发包提供的线程安全的阻塞队列实现。它们分别基于数组和链表来存储元素,并提供了不同的特性和适用场景。ArrayBlockingQueue适合读写性能较高、固定容量的场景;而LinkedBlockingQueue适合插入和删除性能较高、可选有界或无界的场景。在使用时需要根据具体需求选择合适的队列实现。  https://www.bilibili.com/read/cv27006556/ 出处:bilibili

常见线程池

四种拒绝策略:
    RejectedExecutionHandler rejected = null;
    rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
    rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
    rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
    rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务

五种线程池:
    ExecutorService threadPool = null;
    threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
    threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
    threadPool = Executors.newScheduledThreadPool(2);
    threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
    threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多  
                        
原文链接:https://blog.csdn.net/xxj_jing/article/details/84835476

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值