Java线程使用技巧学习(一)
Java线程使用技巧学习(一)
Java线程有哪些不太为人所知的技巧与用法? 萝卜白菜各有所爱。像我就喜欢Java。学无止境,这也是我喜欢它的一个原因。日常工作中你所用到的工具,通常都有些你从来没有了解过的东西,比方说某个方法或者是一些有趣的用法。比如说线程。没错,就是线程。或者确切说是Thread这个类。当我们在构建高可扩展性系统的时候,通常会面临各种各样的并发编程的问题,不过我们现在所要讲的可能会略有不同。 从本文中你将会看到线程提供的一些不太常用的方法及技术。不管你是初学者还是高级用户或者是Java专家,希望都能看一下哪些是你已经知道的,而哪些是刚了解的。如果你认为关于线程还有什么值得分享给大家的,希望能在下面积极回复。那我们就先开始吧。 初学者 1.线程名 程序中的每个线程都有一个名字,创建线程的时候会给它分配一个简单的Java字符串来作为线程名。默认的名字是”Thread-0″, “Thread-1″, “Thread-2″等等。现在有趣的事情来了——Thread提供了两种方式来设置线程名:
- 线程构造函数,下面是最简单的一个实现:
class SuchThread extends Thread {
Public void run() {
System.out.println ("Hi Mom! " + getName());
}
}
SuchThread wow = new SuchThread("much-name");
- 线程名setter方法:
wow.setName(“Just another thread name”);
没错,线程名是可变的。因此我们可以在运行时修改它的名字,而不用在初始化的时候就指定好。name字段其实就是一个简单的字符串对象。也就是说它能达到2³¹-1个字符那么长(Integer.MAX_VALUE)。这足够用了。注意这个名字并不是一个唯一性的标识,因此不同的线程也可以拥有同样的线程名。还有一点就是,不要把null用作线程名,否则会抛出异常(当然了,”null”还是可以的)。 使用线程名来调试问题 既然可以设置线程名,那么如果遵循一定的命名规则的话,出了问题的时候排查起来就能更容易一些。“Thread-6″这样的名字看起来就太没心没肺了,肯定有比它更好的名字。在处理用户请求的时候,可以将事务ID追加到线程名后面,这样能显著减少你排查问题的时间。
“pool-1-thread-1″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800
nid=0x6d03 in Object.wait() [0x000000013ebcc000]
“pool-1-thread-1″,这也太严肃了吧。我们来看下这是什么情况,给它起一个好点的名字:
Thread.currentThread().setName(Context + TID + Params + current Time, ...);
现在我们再来运行下jstack,情况便豁然开朗了:
”Queue Processing Thread, MessageID: AB5CAD, type:
AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956,
Start Time: 30/12/2014 17:37″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800
nid=0x6d03 in Object.wait() [0x000000013ebcc000]
如果我们能知道线程在做什么,这样当它出问题的时候,至少可以拿到事务ID来开始排查。你可以回溯这个问题,复现它,然后定位问题并搞定它。如果你想知道jstack有什么给力的用法,可以看下这篇文章。 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时间上有所体现,不过完全依赖于线程优先级的做法是不推荐的。
- ASP.NET Web API标准的“管道式”设计
- ASP.NET Web API路由系统:Web Host下的URL路由
- ASP.NET Web API路由系统:路由系统的几个核心类型
- [ASP.NET] 如果将缓存“滑动过期时间”设置为1秒会怎样?
- [ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证
- [CORS:跨域资源共享] 同源策略与JSONP
- [CORS:跨域资源共享] W3C的CORS Specification
- 通过扩展让ASP.NET Web API支持JSONP
- ASP.NET Web API自身对CORS的支持:从实例开始
- Generator:化异步为同步
- 超详细的大数据学习资源推荐(下)
- 中国大数据行业发展现状及趋势预测
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构 · 负载均衡的几种类型
- 常用的Hadoop 文件查看工具
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Vue3 模板编译原理
- leetcode树之从上到下打印二叉树
- leetcode树之二叉搜索树的最近公共祖先
- leetcode树之从翻转二叉树
- Linux常见的持久化后门汇总
- 一篇文章带你使用 Python搞定对 Excel 表的读写和处理(xlsx文件的处理)
- 从 rollup 初版源码学习打包原理
- leetcode树之相同的树
- Mysql Sql 语句练习题 (50道)
- 【每日一具16】来了!扫描图片批量漂白修正软件
- 实现一个 webpack loader 和 webpack plugin
- 万字长文带你走进 JavaScript 的世界
- windows中常见后门持久化方法总结
- Python3爬虫实战【点触验证码】 — 模拟登陆bilibili
- BOM 是个什么玩意!