java线程的知识分析

java线程的知识分析

1。线程用于几个方面:

增加 GUI 应用程序的响应速度
利用多处理器系统
当程序有多个独立实体时,简化程序逻辑
在不阻塞整个程序的情况下,执行阻塞 I/O
2。如果对象拥有一个线程,那么它应该提供一个启动该线程的 start() 或 init() 方法,而不是从构造器中启动它。

3。线程结束方式:

线程到达其 run() 方法的末尾。
线程抛出一个未捕获到的 Exception 或 Error。
另一个线程调用一个弃用的 stop() 方法。弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。
4。等待其他线程:
Thread API 包含了等待另一个线程完成的方法:join() 方法。当调用 Thread.join() 时,调用线程将阻塞,直到目标线程完成为止。
5。线程休眠
Thread API 包含了一个 sleep() 方法,它将使当前线程进入等待状态,直到过了一段指定时间,或者直到另一个线程对当前线程的 Thread 对象调用了 Thread.interrupt(),从而中断了线程。当过了指定时间后,线程又将变成可运行的,并且回到调度程序的可运行线程队列中
6。守护程序线程
系统线程称作守护程序线程。Java 程序实际上是在它的所有非守护程序线程完成后退出的。
任何线程都可以变成守护程序线程。可以通过调用 Thread.setDaemon() 方法来指明某个线程是守护程序线程。只有当其它非守护程序线程正在运行时,这些线程才有用。
7。 受控访问的同步
为了确保可以在线程之间以受控方式共享数据,Java 语言提供了两个关键字:synchronized 和 volatile。
Synchronized 有两个重要含义:它确保了一次只有一个线程可以执行代码的受保护部分(互斥,mutual exclusion 或者说 mutex),而且它确保了一个线程更改的数据对于其它线程是可见的(更改的可见性)。
8。Volatile 比同步更简单,只适合于控制对基本变量(整数、布尔变量等)的单个实例的访问。当一个变量被声明成 volatile,任何对该变量的写操作都会绕过高速缓存,直接写入主内存,而任何对该变量的读取也都绕过高速缓存,直接取自主内存。这表示所有线程在任何时候看到的 volatile 变量值都相同。
9。死锁
要避免死锁,应该确保在获取多个锁时,在所有的线程中都以相同的顺序获取锁。
10。synchronized 块时,有几个简单的准则可以遵循:
1)使代码块保持简短。Synchronized 块应该简短 — 在保证相关数据操作的完整性的同时,尽量简短。把不随线程变化的预处理和后处理移出 synchronized 块。
2)不要阻塞。不要在 synchronized 块或方法中调用可能引起阻塞的方法,如 InputStream.read()
3)在持有锁的时候,不要对其它对象调用方法。这听起来可能有些极端,但它消除了最常见的死锁源头。

虽然线程 API 很简单,但编写线程安全的程序并不容易。在线程之间共享变量时,必须非常小心,以确保正确同步了对它们的读写访问。当写一个可能接下来由另一个线程读取的变量,或者读取可能由另一个线程写过的变量时,必须使用同步以确保对数据的更改在线程之间是可见的。

当使用同步保护共享变量时,必须确保不仅使用了同步,而且读取器和写入器在同一个监控器上同步。而且,如果依赖对象的状态在多个操作中保持相同,或者依赖多个变量互相保持一致(或者,与它们过去的值一致),那么必须使用同步来强制实现这一点。但简单地同步一个类中的每一个方法并不能使它变成线程安全的 — 只会使它更容易发生死锁。