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字段其实是一个简单的字符串对象。也是说它能达到231-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()方法来获取及修改它的值。线程的构造函数里是没有这个功能的。