热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java虚拟机_JAVA虚拟机JVM7.多线程常见问题刨析

篇首语:本文由编程笔记#小编为大家整理,主要介绍了JAVA虚拟机JVM-7.多线程常见问题刨析相关的知识,希望对你有一定的参考价值。多线程

篇首语:本文由编程笔记#小编为大家整理,主要介绍了JAVA虚拟机JVM-7.多线程常见问题刨析相关的知识,希望对你有一定的参考价值。




多线程概念


进程与线程

进程是操作系统进行资源分配的最小单位,CPU从一个进程切换到另一个进程叫做进程上下文切换。

线程是CPU调度的最小单位,是进程的一部分,由进程创建,一个进程拥有1~N个线程。线程又分为用户线程和守护线程,两者的区别是,后者会随着主线程结束而结束。


Thread线程类

继承thread类,重写run()方法即可。


wait和slepp的区别



  • wait()方法必须在synchornized同步代码块中使用。

  • wait()方法会释放由synchornized锁上的对象锁,而sleep()不会。

  • 由wait()方法形成的阻塞,可以通过针对同一个对象锁的synchornized作用域调用notify()或者notifyAll()来“唤醒”,而sleep()无法被唤醒,只能定时醒来或者被interrupt()中断。


sleep和yield的区别



  • sleep()执行后转入阻塞,在一段时间后自动醒来,回到就绪状态;而yield方法后,线程直接转入就绪状态。

  • sleep()执行后,其他线程无论优先级高低都可以获取机会运行;而执行yield()只会给相同优先级或者更高优先级的线程运行的机会。

  • sleep()会抛出interruptedException,而yield()没有任何异常声明。

  • sleep()比yield()更好移植,在循环中使用yield()容易产生死循环,当前线程优先级很高,执行yield之后又抢占到了CPU。


Runnable接口

实现runnable接口,实现run()方法。线程池也只能接受Runnable或者Callable接口类型的对象作为线程池任务。


线程池

线程的创建和销毁会消耗资源,在大量并发的情况下,最好是预先创建多个线程,并集中管理,形成一个线程池。


Executor

Java 最开始提供了 ThreadPool 实现了线程池,为了更好地实现用户级的线程调度,更有效地帮助开发人员进行多线程开发,Java 提供了一套 Executor 框架。

 这个框架中包括了 ScheduledThreadPoolExecutor 和 ThreadPoolExecutor 两个核心线程池。前者是用来定时执行任务,后者是用来执行被提交的任务。调用他们的submit()以及execute()方法向线程池提交任务。鉴于这两个线程池的核心原理是一样的,Executors 实现了以下四种类型的 ThreadPoolExecutor:


Callable和Future

这两个接口可以使线程能执行带返回值的任务。


Wait()和Notify()、NotifyAll()

wait()方法会使当前当前线程放弃它持有的对象锁,而进入阻塞状态,而notify()、notifyAll()不会释放对象锁。


线程安全的容器


ConcurrentHashMap

将自身空间划分成若干个segment,并在每个分段各应用一个锁(ReentrantLock),这样减少了锁竞争,也允许一定数量的线程进行读操作,从而提高了并发能力。


ConcurrentSkipListMap/ConcurrentSkipListSet

这两个容器分别是并发的TreeMap以及TreeSet。跳跃表是可以替代平衡二叉树的数据结构,通过“空间换取时间”的算法,实现了线程安全的排序映射表。


CopyOrWriteArrayList/CopyOrWriteArraySet

CopyOrWrite本质是利用高并发时候读多写少的情况,对读不加锁,写的时候复制一份新的集合,在新的集合上面修改,再用新集合替换旧集合。后者是由前者实现的,不同的set在add方法的时候需要调用addIfAbsent()方法,其遍历当前数组。(去掉重复)


ConcurrentLinkedQueue/ConcurrentLinkedDeque

基于链表实现的非阻塞式并发队列和双端队列。


BlockingQueue/BlockingDeque

阻塞式并发队列接口,提供可阻塞的插入put方法以及获取take方法。调用的时候如果队列已满,put方法将阻塞当前线程,队列数据为空时,take方法阻塞当前线程。


ThreadLocal

成为线程本地变量或者线程本地存储,作用是为当前线程提供临时持有和传递对象的方法。


CountDownLatch计数器

java.util.current.CountDownLatch计数器,相当于一个倒序计数器,用来协调多个线程的执行。多个线程调用他们共享的计数器,的countDown()方法让计数器减一。可以通过CountDownLatch对象的await()方法阻塞线程,知道计数器的值为0。


CyclicBarrier栅栏

java.util.current.CyclicBarrier是一种可以重用的线程阻塞器。通过调用await()方法在代码中形成栅栏,率先到达栅栏的线程被栅栏阻塞,知道指定的数量的线程都达到栅栏处。


Semaphore

是用于保护一个或者多个共享资源的访问。内部维护一个计数器,表示同时访问共享资源的的数量。当前成访问共享资源,先要获取一个信号量,如果信号量计数器值大于1,那么可以访问,否则线程被阻塞。


fork/join框架

思想就是将大任务拆分若干个小任务,提高任务的处理速度。


ForkJoinPoll

专门用于执行ForkJoinTask的线程池,而ForkJoinTask被用于封装可以拆分的任务对象,它的两个子类RecursiveActionRecusiveTask分别用于有返回值的任务对象和没有返回值的任务对象。

为了提高多线程处理的效率,避免出现饥饿,Java的fork/join框架采用了一种名为“工作窃取”的方法。每个线程都有自己的双端任务队列,一般情况下线程从头部获取任务,当某个任务队列为空的时候,它会尝试从其它线程任务队列的尾部“窃取任务”来执行。

 

Executors 利用工厂模式实现的四种线程池,我们在使用的时候需要结合生产环境下的实际场景。不过我不太推荐使用它们,因为选择使用 Executors 提供的工厂类,将会忽略很多线程池的参数设置,工厂类一旦选择设置默认参数,就很容易导致无法调优参数设置,从而产生性能问题或者资源浪费。



推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
author-avatar
氵殳冼臉_885
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有