29Java多线程之线程规范与线程管理

完善中……

线程规范

1、线程创建新线程指定名称。

因为指定线程名可以给问题定位带来很多方便。日志或者dump中会包含线程的名称,而缺省的线程名 Thread-n 无法区分出是哪个线程,给问题定位带来不便。

2、不要依赖线程调度器、线程优先级和 yield() 方法

具有不确定性:Java中的线程调度,是基于操作系统以及JVM的实现,在不同的操作系统中,即使是同一套代码,其多线程的调度机制也是不一样的; Thread.yield() 对线程调度器仅仅是个提示,不保证确定的效果。

影响可移植性:如果程序依赖于线程调度器来达到正确性或者性能要求,会导致不可移植;程序如果依赖 Java 的线程优先级来确保正确性,也是不可移植的。

3、采用 Java1.5 提供新并发工具代替 wait()notify() ;

自从 Java1.5 发行版本开始,Java 平台就提供了更高级的并发工具,它们可以完成以前必须 在 wait()notify() 上手写代码来完成的各项工作。 java.util.concurrent 更高级的并发工具分成三类:Executor Framework、并发集合(Concurrent Collection)以及同步器 (Synchronizer)。 性能不是特别苛刻时可以采用 synchronized,简单可读。

原来用 wait()notify() 写的老代码无功能问题,可以保留。

线程管理

1、禁用 Thread 的 run

调用 Thread.start() 方法表示启动一个线程,并执行该线程对应的 run() 方法。但是直接调用 Thread.run() 方法,run() 方法中的语句是由当前线程执行而不是新创建线程来执行。

2、禁用 Thread 的 stop

Thread.stop() 方法已被废弃。线程在正常退出时,会维持类的不变性。某些线程 API 最初是用来帮助线程的暂停、恢复和终止,但随后因为设计上的缺陷而被废弃。例如,Thread.stop() 方法会导致线程立即抛出一个 ThreadDeath 异常,这通常会停止线程。调用 Thread.stop() 会造成一个线程非正常释放它所获得的所有锁,可能会暴露这些锁保护的对象,使这些对象处于一个不一致(不安全)的状态中。

3、线程中断由业务代码来协作完成,慎用 Thread.interrupt 方法

线程中断由业务代码来协作完成,尽量不产生中断异常。

4、避免不加控制地创建新线程,而应该使用线程池来管控资源

5、正确的线程启动与结束流程

建议:依靠业务自身来结束线程任务,利用 volatile 变量控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Test {
public static void main(String[] args) throws InterruptedException {
Mytask task = new Mytask();
Thread thread = new Thread(task, "task");
thread.start();;
Thread.sleep(5000);
task.finish();
}
}

final class Mytask implements Runnable {
private volatile boolean isFinished = false;

@Override
public void run() {
while (!isFinished) {
// ...
}
}

public void finish() {
isFinished = true;
}
}

小测

以下有关Thread异常处理说法正确的是(多选) BCD

A.子线程自身不必捕获异常,而是由主线程捕获即可

B.对于运行时异常可调用 Thread.setUncaughtExceptionHandler() 方法设置运行时异常处理器来进行处理

C.默认情况下,运行时异常从线程抛出时,会在控制台输出堆栈记录

D.子线程须自己捕获异常处理