在指定的毫秒数内,让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有synchronized 同步块,其他线程仍然不能访问共享数据。注意该方法要捕获异常。
比如有两个线程同时执行(没有 synchronized),一个线程优先级为MAX_PRIORITY ,另一个为 MIN_PRIORITY 。
yield 方法和 sleep 方法类似,也不会释放“锁标志”,区别在于:
Thread 的非静态方法 join ,让一个线程 B “加入”到另外一个线程 A 的尾部。在线程 A 执行完毕之前,线程 B 不能工作。示例代码如下:
Thread t = new MyThread();
t.start();
t.join();
保证当前线程停止执行,直到该线程所加入的线程 t 完成为止。然而,如果它加入的线程 t 没有存活,则当前线程不需要停止。
Thread 类的 sleep 和 yield 方法,将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。
Thread#sleep(0) 方法,并非是真的要线程挂起 0 毫秒,意义在于这次调用 Thread#sleep(0) 方法,把当前线程确实的被冻结了一下,让其他线程有机会优先执行。Thread#sleep(0) 方法,是你的线程暂时放弃 CPU ,也就是释放一些未用的时间片给其他线程或进程使用,就相当于一个让位动作。
我们可以使用 Thread 类的 #join() 方法,来确保所有程序创建的线程在 main 方法退出前结束。
Thread#interrupt() 方法,用于中断线程。调用该方法的线程的状态为将被置为”中断”状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出 InterruptedException 的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
Thread#interrupted() 静态方法,查询当前线程的中断状态,并且清除原状态。如果一个线程被中断了,第一次调用 #interrupted() 方法则返回 true ,第二次和后面的就返回 false 了。
// Thread.java
public static boolean interrupted() {
return currentThread().isInterrupted(true); // 清理
}
private native boolean isInterrupted(boolean ClearInterrupted);
Thread#isInterrupted() 方法,查询指定线程的中断状态,不会清除原状态。代码如下:
// Thread.java
public boolean isInterrupted() {
return isInterrupted(false); // 不清楚
}
private native boolean isInterrupted(boolean ClearInterrupted);
线程安全,是编程中的术语,指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。
Servlet 不是线程安全的,Servlet 是单实例多线程的,当多个线程同时访问同一个方法,是不能保证共享变量的线程安全性的。
Struts2 的 Action 是多实例多线程的,是线程安全的,每个请求过来都会 new 一个新的 Action 分配给这个请求,请求完成后销毁。
不是的,和 Servlet 类似的处理流程。
例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,总结一下:
线程同步,是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
线程间的同步方法,大体可分为两类:用户模式和内核模式。顾名思义:
线程互斥,是指对于共享的进程系统资源,在各单个线程访问时的排它性。
在两个线程间共享变量,即可实现共享。
一般来说,共享变量要求变量本身是线程安全的,然后在线程内使用的时候,如果有对共享变量的复合操作,那么也得保证复合操作的线程安全性。
调用 Thread#holdsLock(Object obj) 静态方法,它返回 true 如果当且仅当当前线程拥有某个具体对象的锁。代码如下:
public static native boolean holdsLock(Object obj);
从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。
但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。
ThreadLocal ,是 Java 里一种特殊的变量。每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。
它是为创建代价高昂的对象获取线程安全的好方法,比如你可以用 ThreadLocal 让 SimpleDateFormat 变成线程安全的,因为那个类创建代价高昂且每次调用都需要创建不同的实例所以不值得在局部范围使用它,如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。
InheritableThreadLocal 类,是 ThreadLocal 类的子类。ThreadLocal 中每个线程拥有它自己的值,与 ThreadLocal 不同的是,InheritableThreadLocal 允许一个线程以及该线程创建的所有子线程都可以访问它保存的值。
不是,非常不幸,DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如将 SimpleDateFormat 限制在 ThreadLocal 中。
如果你不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、时间处理的所有实践来说,我强力推荐 joda-time 库。