线程安全
很重要的概念。
多线程访问同一段代码,不会产生不确定的结果。则可以说这段代码是线程安全的。
常用方法
调用
sleep()的时候,锁并没有被释放,调用yield()也属于这种情况;而wait()方法会将锁释放。
只能在同步控制方法或同步控制块里面调用 wait()、notify()、notifyAll()。如果在非同步控制块中调用这些方法,能通过编译但运行会出错,得到IllegalMonitorStateException异常。
当调用某个ExecutorService的shutdownNow()时,它会调用 所有 由它控制的 线程的interrupt()。
只能在同步控制方法或同步控制块里面调用 wait()、notify()、notifyAll()。如果在非同步控制块中调用这些方法,能通过编译但运行会出错,得到IllegalMonitorStateException异常。
当调用某个ExecutorService的shutdownNow()时,它会调用 所有 由它控制的 线程的interrupt()。
Thread.
yield()告诉java线程调度器“重要的部分我已经完成,此刻可以将我挂起,切换给其他线程执行”。这个函数可用可不用,但用了它更容易按照自己的掌控去切换线程,从而验证一些东西。
调用 wait()时,执行两个动作:挂起线程,释放锁。
别的地方调用notifyAll(),将唤醒wait()所挂起的线程。在线程继续运行之前将重新获得上次wait()调用时释放的锁。
使用 notify()时,在众多等待同一个锁的任务中只有一个会被唤醒。
notifyAll()唤醒所有等待同一个锁的任务。注意,这并不意味着在程序的任何地方,任何被wait()挂起的线程都会被唤醒,。当notifyAll()因为某个特定锁而被调用时,只有等待这个锁的任务才会被唤醒。
调用 wait()时,执行两个动作:挂起线程,释放锁。
别的地方调用notifyAll(),将唤醒wait()所挂起的线程。在线程继续运行之前将重新获得上次wait()调用时释放的锁。
使用 notify()时,在众多等待同一个锁的任务中只有一个会被唤醒。
notifyAll()唤醒所有等待同一个锁的任务。注意,这并不意味着在程序的任何地方,任何被wait()挂起的线程都会被唤醒,。当notifyAll()因为某个特定锁而被调用时,只有等待这个锁的任务才会被唤醒。
打蜡、抛光在多个线程中交替进行。
需要一个状态切换的标志位,两对wait()、notify()操作。
一:Thinking in Java 的例子
//: concurrency/waxomatic/WaxOMatic.java// Basic task cooperation.import java.util.concurrent.* ;
class Car {private boolean waxOn = false ; //true表示打完蜡该抛光了public synchronized void waxed () { // 已打蜡,可以抛光了waxOn = true ;System . out . println ( "waxed!" );notifyAll ();}public synchronized void buffed () { // 已抛光,(下辆车)可以打蜡啦waxOn = false ;System . out . println ( "buffed!" );notifyAll ();}public synchronized void waitForWaxing () //已打蜡情况下返回throws InterruptedException {while ( waxOn == false )wait ();}public synchronized void waitForBuffing () //已抛光情况下返回throws InterruptedException {while ( waxOn == true )wait ();}}
class Wax implements Runnable {private Car car ;public Wax ( Car c ) { car = c ; }public void run () {try {while (! Thread . interrupted ()) {TimeUnit . MILLISECONDS . sleep ( 200 );car . waxed ();car . waitForBuffing ();}} catch ( InterruptedException e ) {System . out . println ( "Exiting via interrupt" );}System . out . println ( "Ending Wax On task" );}}
class Buff implements Runnable {private Car car ;public Buff ( Car c ) { car = c ; }public void run () {try {while (! Thread . interrupted ()) {car . waitForWaxing ();TimeUnit . MILLISECONDS . sleep ( 200 );car . buffed ();}} catch ( InterruptedException e ) {System . out . println ( "Exiting via interrupt" );}System . out . println ( "Ending Wax Off task" );}}
public class WaxOMatic {public static void main ( String [] args ) throws Exception {Car car = new Car ();ExecutorService exec = Executors . newCachedThreadPool ();exec . execute ( new Buff ( car ));exec . execute ( new Wax ( car ));TimeUnit . SECONDS . sleep ( 2 ); // Run for a while...exec . shutdownNow (); // Interrupt all tasks}} /*waxed!buffed!waxed!buffed!waxed!buffed!waxed!buffed!waxed!buffed!Exiting via interruptEnding Wax On taskExiting via interruptEnding Wax Off task*/
调试时可以看到有三个线程,很直观。