在线客服
扫描二维码
下载博学谷APP扫描二维码
关注博学谷微信公众号
Java开发线程特点基础知识分享,线程提供的一些不太常用的方法及技术不管是初学者还是高级用户或者是Java专家都需要了解。掌握线程、进程、多线程、并发、并行、同步、异步、线程类常见方法、线程生命周期、线程安全问题、死锁、生产者和消费者等多线程核心知识点。
初学者阶段:
1、线程名
程序中的每个线程都有一个名字,创建线程的时候会给它分配一个简单的Java字符串来作为线程名。默认的名字是”Thread-0″, “Thread-1″, “Thread-2″等。
线程名可变,可在运行时修改它的名字,而不用在初始化的时候就指定好。name字段其实是一个简单的字符串对象,它能达到2³¹-1个字符那么长足够用了。这个名字并不是一个唯一性的标识,因此不同的线程也可以拥有同样的线程名。还有一点不要把null用作线程名否则会抛出异常。
使用线程名来调试问题
既然可以设置线程名,如果遵循一定的命名规则出问题的时候排查起来就能更容易。在处理用户请求的时候可以将事务ID追加到线程名后面,能减少排查问题的时间。
2. 线程优先级
线程还有一个有意思的属性优先级。线程的优先级介于1 (MINPRIORITY)到10 (MAXPRIORITY)之间,主线程默认是5(NORM_PRIORITY)。每个新线程都默认继承父线程的优先级,如果没设置过,所有线程的优先级都是5。这个是通常被忽视的属性,可以通过getPriority()与setPriority()方法来获取及修改它的值。线程的构造函数里是没有这个功能。
什么地方会用到优先级?
不是所有的线程都是平等的,有的线程需要立即引起CPU重视,而有些线程则只是后台任务。优先级就是用来把这些告诉给操作系统的线程调度器。在Takipi中开发的一错误跟踪及排查的工具,负责处理用户异常的线程的优先级是MAX_PRIORITY,而那些只是在上报新的部署情况的线程,优先级就要低一些。优先级高的线程从JVM的线程调度器那得到的时间会多一些,但其实并非是这样的。
在操作系统层面每一个新线程都会对应一个本地线程,所设置的Java线程的优先级会被转化成本地线程的优先级,这个在各个平台上不一样。在Linux上可以打开“-XX:+UseThreadPriorities”选项来启用这项功能。线程优先级只是所提供的一个建议,和Linux本地的优先级相比Java线程的优先级并不能覆盖全所有的级别(Linux共有1到99个优先级,线程的优先级在是-20到20之间)。最大的好处所设定的优先级能在每个线程获得的CPU时间上有所体现,不过完全依赖于线程优先级的做法不推荐。
进阶阶段:
3、线程本地存储
ThreadLocal是在Thread类之外实现的一个功能(java.lang.ThreadLocal),但它会为每个线程分别存储一份唯一的数据。正如它的名字所说的,它为线程提供了本地存储,也就是说所创建出来变量对每个线程实例来说都是唯一的。和线程名,线程优先级类似可以自定义出一些属性,像存储在Thread线程内部一样。
全局变量不是什么好事
ThreadLocal可以用来存储事务ID。如果代码中出现未捕获异常的时候它就相当有用了,最佳实践是设置一个UncaughtExceptionHandler,这个是Thread类本身就支持的,但是得自己去实现一下这个接口。一旦执行到了UncaughtExceptionHandler里,几乎没有任何线索能够知道到底发生了什么事情了。这会儿能获取到的就只有Thread对象,之前导致异常发生的所有变量都无法再访问了,因为那些栈帧都已经被弹出了。一旦到了UncaughtExceptionHandler里,这个线程就只剩下最后一口气了,唯一能抓住的最后一根稻草就是ThreadLocal。
4、用户线程及守护线程
Thread类。程序中的每个线程都会有一个状态,是用户状态或是守护状态。换句话说,前台线程或是后台线程,主线程默认是用户线程,每个新线程都会从创建它的线程中继承线程状态。如果把一个线程设置成守护线程,那么它所创建的所有线程都会被标记成守护线程。如果程序中的所有线程都是守护线程的话,那么这个进程便会终止。可以通过Boolean .setDaemon(true)和.isDaemon()方法来查看及设置线程状态。
什么时候会用到守护线程?
如果进程不必等到某个线程结束才能终止,那么这个线程就可以设置成守护线程。这省掉了正常关闭线程的那些麻烦事,可以立即将线程结束掉。换个角度来说,如果一个正在执行某个操作的线程必须要正确地关闭掉否则就会出现不好的后果的话,那么这个线程就应该是用户线程。通常都是些关键的事务,比方说,数据库录入或者更新这些操作不能中断。
高级阶段:
5、处理器亲和性
这里要讲的会更靠近硬件,当软件遇上了硬件。处理器亲和性使得能够将线程或者进程绑定到特定的CPU核上。这意味着只要是某个特定的线程,肯定只会在某个特定的CPU核上执行。通常来讲如何绑定是由操作系统的线程调度器根据它自己的逻辑来决定的,它很可能会将前面提到的线程优先级也一并考虑进来。
这么做的好处在于CPU缓存。如果某个线程只会在某个核上运行,那么它的数据恰好在缓存里的概率就大大提高了。如果数据正好就在CPU缓存里,那么就没有必要重新再从内存里加载了。所节省的这几毫秒时间就能用在刀刃上,在这段时间里代码可以马上开始执行,也就能更好地利用所分配给它的CPU时间。当然了,操作系统层面可能会存在某种优化,硬件架构当然也是个很重要的因素,但利用了处理器的亲和性至少能够减小线程切换CPU的机率。
由于掺杂着多种因素处理器亲和性到底对吞吐量有多大的影响,最好还是通过测试的方式来进行证明。也许这个方法并不是总能显著地提升性能,但至少有一个好处就是吞吐量会相对稳定。亲和策略可以细化到非常细的粒度上取决于具体想要什么,高频交易行业便是这一策略最能大显身手的场景之一。
— 申请免费试学名额 —
在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!
相关推荐 更多
Java基础 能不能自己写个类也叫 java.lang.String?
Java基础知识,能不能自己写个类也叫 java.lang.String?可以,但在应用的时候,需要用自己的类加载器去加载,否则,系统的类加载器永远只是去加载 jre.jar 包中的那个java.lang.String。
8452
2019-06-03 14:33:13
Java多线程基础知识讲解
Java支持多线程编程,因此用Java编写的应用程序可以同时执行多个任务。Java的多线程机制使用起来非常方便,用户只需关注程序细节的实现,而不用担心后台的多任务系统。本文将为大家讲解有关Java多线程的基础知识,主要内容有多线程的概念、创建、优势和生命周期。
6813
2019-08-21 10:53:43
Java基础语法学习DQL查询语句
DQL查询语句只是一种显示数据的方式,因此不会对数据库中的数据进行修改。简单来讲,DQL查询语句有以下四种查询方法,分别是排序查询、聚合函数、分组查询和分页查询。今天要学习的Java基础语法就是关于DQL查询语句的四种查询方式介绍,需要学习了解这方面知识点的小伙伴,一起来看看相关知识点的梳理吧!
4635
2020-01-08 10:43:28
Redis选择单线程模型的原因分析
双线程的程序可以支持每秒几百万的请求量,众所周知,Redis 作为被广泛使用的内存数据库偏偏选择了单线程模型,这又是为什么呢?其实简单概括起来主要有以下三个原因,方便维护,可以并发的处理任务以及双线程不能解决Redis的性能瓶颈。下面我们来仔细分析一下Redis选择单线程模型的原因。
5025
2020-03-10 18:41:44
Java基础入门数组学习笔记
众所周知,数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致。要想入门Java,数组是一个必须好好学习的基础知识点。本文为广大Java基础入门初学者归纳总结了数组的学习笔记,下面一起来看看吧~
3940
2020-05-25 15:33:04