![](https://img-blog.csdnimg.cn/20201014180756918.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
八、并发编程
并发编程
还能在学一小时
这个作者很懒,什么都没留下…
展开
-
什么是阻塞队列,举几个应用场景
阻塞队列(BlockingQueue)是一种特殊类型的队列,它用于在多线程环境中实现线程之间的通信。常见的Java阻塞队列实现包括:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue等。总之,阻塞队列是一种非常有用的工具,它可以帮助程序员在多线程环境中实现线程之间的通信和同步。原创 2024-01-15 11:08:49 · 525 阅读 · 0 评论 -
说下Fork/Join框架,与传统线程池有何不同
Fork/Join框架的核心是ForkJoinPool,它是一种特殊的线程池,它使用工作窃取算法(Work-Stealing)来平衡负载,使得每个线程尽可能均匀地执行任务。总之,Fork/Join框架是一种专门用于并行化执行任务的框架,它通过分治法策略和自动并行化功能,使得程序员可以更方便地利用多核CPU的性能优势。,它是Java 7引入的一个新特性,专门用于方便地利用多核CPU的性能优势,通过分治法的策略来将任务分解为更小的子任务,然后并行执行这些子任务,最后再合并子任务的结果。原创 2024-01-15 11:24:09 · 701 阅读 · 0 评论 -
说说并发和并行的区别
针对单核 CPU 而言,它指的是 多个任务交替执行,每个任务都会在一段时间内执行一部分,然后切换到另一个任务,因为单核 CPU 一次只能执行一个任务。针对多核 CPU 而言,它指的是多个任务真正同时执行,每个任务都有自己的处理器核心,它们可以在同一时刻执行不同的指令。并行的目的是提高计算能力和性能,允许多个任务同时处理,以加快任务完成的速度。多个任务可以在不同的核心上并行执行,并且每个任务内部可能也包含并发的逻辑,以处理不同的子任务。这样可以最大程度地提高系统的性能和响应性。原创 2024-01-15 11:37:49 · 349 阅读 · 0 评论 -
说说进程和线程的区别
线程被视为操作系统调度的最小单元,它们共享相同的进程内存空间和系统资源。在一个进程内,多个线程可以协同工作,执行不同的任务,共享数据。例如,一个文字处理软件的进程可能包括一个主线程,用于处理用户界面响应,同时还有一个后台线程,负责自动保存文件。当一个程序在计算机上运行时,通常会创建至少一个进程。进程被认为是操作系统分配资源的最小单元,每个进程都拥有独立的内存空间和系统资源,包括文件句柄和网络连接等。比如,你的计算机上可能同时运行着浏览器、文本编辑器、音乐播放器等多个进程。原创 2024-01-15 13:45:00 · 390 阅读 · 0 评论 -
JAVA 守护线程和本地线程的区别
可以看作是为其他线程提供服务的辅助工具。它们通常执行一些后台任务,比如垃圾回收、定期检查、日志记录等。一个重要的特点是它们不会阻止JVM的退出。当所有的本地线程都执行完毕后,JVM会自动退出,不会等待守护线程。,则是应用程序的主力军,执行着应用的核心逻辑。它们的存在会阻止JVM退出,因为只要还有本地线程在运行,JVM会继续工作。来告诉JVM它是守护线程。而本地线程则是默认的线程类型,不需要额外设置。至于如何创建它们,守护线程需要通过设置。原创 2024-01-15 14:10:51 · 355 阅读 · 0 评论 -
启动线程为何调用start而不是run方法
通过调用 start() 方法,可以利用多核处理器的优势,同时执行多个线程,以更有效地完成任务。而直接调用 run() 方法只是按照一般的方法顺序执行代码,无法发挥多线程的潜力。,并在这个新线程中执行与 run() 方法相关联的代码块。这个过程允许多个线程同时运行,每个线程都拥有独立的执行上下文,这意味着它们可以在不互相干扰的情况下执行任务。相反,它会在当前线程的上下文中执行 run() 方法中的代码。这将导致代码的顺序执行,没有并行性可言,因为它们都在同一个线程内执行。原创 2024-01-15 14:38:07 · 384 阅读 · 0 评论 -
Java线程之间是如何通信的
这种方式通常涉及线程之间的显式消息发送和接收操作,使线程能够协调它们的工作。例如,我们可以使用信号量机制,通过获取和释放许可证来控制线程的访问。此外,锁机制也是一种重要的消息传递方式,通过获取和释放锁来实现线程之间的互斥和同步。消息传递的优点在于可以实现更松散的耦合,线程之间不需要直接共享内存,从而减少了潜在的竞争条件。这是一种常见的方式,多个线程可以访问同一个共享内存区域,通过读取和写入共享内存中的数据来进行通信和同步。关键字来确保共享变量的可见性,以及使用等待和通知机制,即。原创 2024-01-15 14:52:19 · 343 阅读 · 0 评论 -
Java 中用到的线程调度算法是什么
如果线程具有相同的优先级,那么Java虚拟机会随机选择一个线程来执行,以保持公平竞争的原则。一旦一个线程获得了CPU,它将一直运行,直到自愿放弃CPU资源,或者由于某些情况(比如等待I/O操作、等待锁等)被迫放弃CPU,从而让其他线程有机会执行。这种抢占式调度模型的目标是确保具有较高优先级的线程在争夺CPU资源时具有优势,但仍然让较低优先级的线程有机会执行,以避免它们被永远地忽略。Java的多线程调度机制有助于平衡线程之间的竞争和公平性,从而提高了多线程程序的响应速度和效率。原创 2024-01-15 15:19:09 · 382 阅读 · 0 评论 -
死锁与活锁,死锁与饥饿的区别
是指一个或多个线程或进程由于某种原因无法获得所需的资源或执行机会,因此无法适时地执行。在饥饿中,线程不一定被永久性地阻塞,但是它们可能长时间无法获得所需的资源。是指多个线程不断地改变自己的状态以回应对方,但最终无法取得进展,导致线程不断重试相同的操作,却无法成功。活锁通常发生在线程在避免冲突时不断改变状态,但却没有成功,就像两个人在狭窄的道路上不断让对方走,却无法通过一样。这是一种静止状态,这种情况会导致所有线程都被永久性地阻塞,没有一个线程能够继续执行。就像交通堵塞一样,没有车辆能够前进。原创 2024-01-16 09:24:29 · 419 阅读 · 0 评论 -
如何避免死锁
死锁是多线程编程中的一种常见问题,它发生在两个或多个线程相互等待对方释放资源的情况下,导致程序无法继续执行。原创 2024-01-16 09:35:54 · 361 阅读 · 0 评论 -
什么情况线程会进入 WAITING 状态
需要注意的是,当线程进入WAITING状态时,会释放所有的锁,并且不会占用CPU资源。如果线程长时间处于等待状态,可能会造成CPU的空闲,因此需要注意避免出现不必要的等待。原创 2024-01-16 09:46:50 · 655 阅读 · 0 评论 -
说说synchronized与ReentrantLock的区别
用法不同:synchronized 可以用于修饰普通方法、静态方法以及代码块,而 ReentrantLock 仅适用于代码块。 获取锁和释放锁方式不同:Synchronized 是隐式锁,可以自动加锁和释放锁,当进入 synchronized 修饰的代码块之后会自动加锁,当离开 synchronized 的代码段之后会自动释放锁。ReentrantLock 是显式锁,需要手动加锁和释放锁, 在使用之前需要先创建 ReentrantLock 对象,然后使用 lock 方法进行加锁,使用完之后再调用 unlo原创 2024-01-16 09:56:35 · 365 阅读 · 0 评论 -
ThreadLocaL如何防止内存泄漏
3、使用 InheritableThreadLocal:如果需要在子线程中访问父线程的 ThreadLocal 变量,并且确保在子线程中正确清理,可以考虑使用 InheritableThreadLocal。2、使用 try-with-resources 或 try-finally 块:如果你的 ThreadLocal 变量在需要清理的资源管理上下文中使用,可以使用 try-with-resources(自动清理)或 try-finally(手动清理)块来确保及时清理。原创 2024-01-16 10:15:34 · 506 阅读 · 0 评论 -
说说ThreadLocal原理
这样可以实现线程之间的数据隔离,从而有效地避免了线程安全问题。但需要谨慎使用 ThreadLocal,确保在不再需要时及时清理变量副本,以避免潜在的内存泄漏问题。这种机制提供了一种有效的方式来确保线程级别的数据隔离和线程安全性。ThreadLocal 是 Java 中的一个类,用于实现线程封闭(Thread-local)的数据存储机制。每个线程都有自己的 ThreadLocalMap,其中 ThreadLocal 对象充当键,线程的变量副本作为对应键的值。使用 ThreadLocal 的。原创 2024-01-16 10:34:12 · 341 阅读 · 0 评论 -
为什么 wait 和 notify 方法要在同步块中调用
简而言之,将 wait() 和 notify() 方法包裹在同步块内,有助于确保线程间的协同和同步工作正确,避免了多线程问题,提高了程序的可靠性和安全性。原创 2024-01-16 10:49:53 · 519 阅读 · 0 评论 -
有三个线程T1,T2,T3,如何保证顺序执行
确保三个线程 T1、T2、T3 按照指定顺序执行有多种方式。这些方法都可以用来确保线程按照指定顺序执行。选择其中一种方式取决于你的具体需求和场景。原创 2024-01-16 10:56:11 · 449 阅读 · 0 评论 -
线程池中核心线程数量大小怎么设置
比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间。IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间。:比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务,大部分场景下都是纯 CPU 计算。因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换。另外:线程的平均工作时间所占比例越高,就需要越少的线程;原创 2024-01-16 11:04:41 · 393 阅读 · 0 评论 -
如何确保线程安全
在实现线程安全时,还需要考虑其他问题,如避免死锁、合理地控制并发量等。同时,应该避免使用非线程安全的数据结构和方法,避免使用可能会引起竞态条件和数据不一致的操作。确保线程安全可以通过多种方法和技术来实现。原创 2024-01-16 11:17:11 · 401 阅读 · 0 评论 -
什么是可重入锁
但是需要注意,在使用可重入锁时,必须保证在释放锁之前已经获取了该锁,否则会导致死锁。同时还需要保证在获取锁的时候没有嵌套地获取其他锁,否则也会导致死锁。举个例子,假设有一个线程A在执行一个方法,同时这个方法内部又调用另一个方法,那么线程A可以重复获取同一个锁,而不会出现死锁的情况。可重入锁可以简单理解为一个可以重复获取的锁,就像拿钥匙开锁一样,你可以反复用同一把钥匙开锁。这种锁在同一线程内是安全的,因为它可以被同一线程多次获取,而不会产生不一致的状态。总之,可重入锁是一种安全的锁机制,可以避免死锁的发生。原创 2024-01-16 11:27:37 · 348 阅读 · 0 评论 -
锁的优化机制了解吗
锁的优化机制是Java等编程语言中常见的一种提高并发性能的方法。锁的优化旨在减少锁的竞争,从而提高程序的性能。这些锁的优化机制都有各自的适用场景和优缺点,需要根据具体的业务需求和性能要求来选择合适的锁机制。原创 2024-01-16 11:35:22 · 394 阅读 · 0 评论 -
什么是不可变对象,对写并发有什么帮助
需要注意的是,虽然不可变对象有以上优点,但它们也有一些缺点。例如,创建新的不可变对象比创建可变对象需要更多的内存,因为每次状态改变都需要创建新的对象。因此,在设计并发应用时,应根据具体需求和性能要求来决定是否使用不可变对象。不可变对象(Immutable object)是一种一旦创建后其状态就不能被修改的对象。在Java中,不可变对象包括String、基本类型的包装类(如Integer、Double等)等。原创 2024-01-16 13:47:17 · 408 阅读 · 0 评论 -
说说你对JMM内存模型的理解
Java内存模型(JMM)是一种抽象的概念,用于描述在Java程序中,一组线程如何通过共享内存进行交互。JMM并不真实存在,它是一种规范,规定了程序中变量在内存中的访问方式。其中最重要的规则是:当一个线程想要访问一个共享变量的值时,它必须先将其本地内存中的值更新到主内存中,然后再从主内存中读取该变量的值。同时,JMM也规范了JVM如何与计算机内存进行交互,从而保证并发程序的正确性和可靠性。主内存存储了所有的对象实例和静态变量,而工作内存存储了每个线程的局部变量、栈中的部分区域以及寄存器的内容。原创 2024-01-16 13:58:41 · 388 阅读 · 0 评论 -
说下对AQS的理解
AQS(AbstractQueuedSynchronizer)是Java并发编程中的一个重要组件,它是一个抽象类,提供了线程同步的底层实现机制。AQS的作用是实现线程的同步和互斥操作,它提供了两种主要的锁机制,分别是排他锁和共享锁。当同步状态为0时,表示锁是未被获取的;当线程需要获取锁资源时,如果锁已经被其他线程获取,则该线程会被加入到等待队列中等待。在使用AQS时,需要根据具体的应用场景选择合适的锁机制来实现线程的同步和互斥操作。在AQS中,共享锁的实现与排他锁类似,也是通过内置的同步状态来实现的。原创 2024-01-17 09:31:10 · 381 阅读 · 0 评论 -
说下CAS的原理
ABA问题是指一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。开销问题则是因为CAS自旋操作需要不断轮询内存位置,直到成功为止,这会消耗大量的CPU资源。CAS(Compare And Swap)是一种乐观的并发控制机制,它的核心原理是基于硬件层面的原子性保证。CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。然而,CAS也存在一些缺点,例如。原创 2024-01-17 09:39:39 · 319 阅读 · 0 评论 -
如何停止一个正在运行的线程
要停止一个正在运行的线程,通常有几种方法,但需要根据具体情况选择适当的方式,因为线程的停止涉及到线程安全和资源释放等问题。在线程的执行体中使用一个标志位,当该标志位为true时,线程会自行退出执行。方法可以强制停止一个线程,但不建议使用它,因为它可能导致线程的状态不一致和资源泄漏等问题,容易引发不可预测的错误。在这种方法中,线程需要主动检查是否被中断,并根据需要停止执行。方法,并在线程的执行体中检查相应的标志或中断状态。方法可以中断线程的执行。标志位,从而停止线程的执行。方法来停止线程池中的线程。原创 2024-01-17 09:50:59 · 342 阅读 · 0 评论 -
JAVA 中有几种方法可以实现一个线程
接口或使用Lambda表达式的方式来创建线程,因为它们更加灵活,可以避免Java单继承的限制,并且符合面向对象的设计原则。在Java 8及以后的版本中,可以使用Lambda表达式来创建线程对象,更加简洁。这些方法都可以用来创建和启动线程,选择哪种方式取决于具体的需求和编程风格。可以使用匿名内部类来创建线程对象,这种方式通常用于简单的线程任务。创建一个继承自Thread类的子类,然后重写子类的。,可以提交任务并由线程池管理线程的生命周期。框架中的线程池来管理和执行线程。方法,将线程的任务逻辑放在。原创 2024-01-17 09:58:38 · 473 阅读 · 0 评论 -
ReentrantLock中的公平锁和非公平锁的底层实现
需要注意的是,公平锁虽然遵循公平性原则,但在高并发情况下可能会引入较大的性能开销,因为每次都要维护一个有序的等待队列。而非公平锁则更加灵活,但可能导致某些线程一直获取不到锁。底层实现中,无论是公平锁还是非公平锁,都使用了类似的同步器(Sync)来管理锁的状态和线程的竞争。不同之处在于如何处理等待队列中的线程,以及是否按照请求的顺序来分配锁。原创 2024-01-17 10:09:49 · 399 阅读 · 0 评论 -
JAVA 中怎样唤醒一个阻塞的线程
当线程被中断后,会设置线程的中断状态为true。在代码中可以通过Thread.currentThread().isInterrupted()方法来检查线程的中断状态。如果线程检测到自己被中断,那么可以根据中断状态做出相应的处理。在Java中,被中断的线程需要自己编写代码去响应中断,否则线程仍然会一直阻塞。因此,在实际应用中,需要根据具体的业务逻辑编写相应的中断处理代码。在Java中,可以使用Thread类的interrupt()方法来唤醒一个阻塞的线程。原创 2024-01-17 10:20:00 · 461 阅读 · 0 评论 -
什么是线程调度器和时间分片
时间分片(Time Slicing)是指将可用的 CPU 时间分配给可用的 Runnable 线程的过程。这样,每个线程运行一段时间后,会被暂停,然后调度器会选择下一个线程来执行。这种方式可以确保每个线程都能获得一定的运行时间,从而实现多任务并发执行。线程调度器(Thread Scheduler)是操作系统内核中的一个重要组件,负责分配并管理处理器时间片,控制多线程程序的执行顺序。当有多个线程同时运行时,线程调度器会在这些线程之间进行切换,使得每个线程都有机会使用 CPU 资源,并实现任务的并发执行。原创 2024-01-17 10:27:22 · 420 阅读 · 0 评论 -
说下你对volatile的理解
总的来说,volatile可以确保多个线程对共享变量的操作一致,避免了数据不一致的问题。但是它不能保证原子性,因此对于需要保证原子性的操作,还需要使用其他同步机制,如synchronized关键字或java.util.concurrent.atomic包中的原子类。原创 2024-01-17 10:38:25 · 322 阅读 · 0 评论 -
JDK7与JDK8之间HashMap的区别?
JDK8中新增了红黑树,JDK8是通过数组+链表+红黑树来实现的; JDK7中链表的插入是用的头插法,而JDK8中则改为了尾插法; JDK8中的因为使用了红黑树保证了插入和查询了效率,所以实际上JDK8中的Hash算法实现的复杂度降低了; JDK8中数组扩容的条件也发了变化,只会判断是否当前元素个数是否查过了阈值,而不再判断当前put进来的元素对应的数组下标位置是否有值; JDK7中是先扩容再添加新元素,JDK8中是先添加新元素然后再扩容。原创 2024-01-17 10:47:37 · 376 阅读 · 0 评论 -
说下ConcurrentHashMap和Hashtable的异同点
中的一些限制和性能瓶颈。然而,在某些情况下,如果不需要特定的高并发性能要求,是在多线程环境中更常用的选择,因为它提供了更好的性能和灵活性,同时避免了。仍然可以用作线程安全的数据结构。原创 2024-01-17 10:55:22 · 353 阅读 · 0 评论 -
线程池中线程复用原理
线程复用的关键是将任务的提交和线程的创建、管理、执行分离,通过线程池来统一管理和调度,减少了创建和销毁线程的开销,提高了系统的效率。同时,由于线程池的复用特性,可以有效控制并发度,避免大量线程的创建和销毁导致的系统负载过大。线程池中的线程数量是有限的,核心线程数通常是固定的,最大线程数可以设置,超过最大线程数后,任务会被拒绝。线程池会对线程进行封装,核心原理在于将线程的创建和管理与任务的执行分离。线程池的线程复用原理是指,将线程放入线程池中重复利用,,如果是,则新建一个线程来执行任务;原创 2024-01-17 11:04:52 · 563 阅读 · 1 评论 -
线程池的底层工作原理
总的来说,线程池的底层工作原理是通过管理一组工作线程、任务队列和任务分配策略来实现任务的调度和执行。这种机制可以提高线程的重用性、提高程序性能,并有效地控制线程的生命周期,使得线程池成为多线程编程中的重要工具。线程池是一种用于管理和重用线程的机制,其底层工作原理涉及线程的创建、调度、执行以及回收等关键过程。原创 2024-01-17 11:13:41 · 511 阅读 · 0 评论 -
线程池的哪些参数影响性能
这些参数的合理配置取决于实际情况,包括任务的数量、性质以及可用资源等因素。通过正确选择和调整这些参数,可以优化线程池的性能,确保它能够高效地处理任务并避免资源浪费。原创 2024-01-17 11:23:42 · 422 阅读 · 0 评论 -
如何优化线程池的性能
总之,在优化线程池性能时,需要根据实际情况进行参数配置,并选择合适的队列类型和任务拒绝策略。同时,还需要注意系统资源的利用和线程池的可维护性。要优化线程池的性能,需要根据实际情况进行参数配置。原创 2024-01-17 11:32:11 · 549 阅读 · 0 评论 -
判断线程池任务执行完成的方式
Thread线程是否执行完成,我们可以调用join方法然后等待线程执行完成;那在使用线程池的时候,我们如何知道线程已经执行完成了?本文就带给大家。原创 2024-01-17 11:40:13 · 2148 阅读 · 0 评论