go4it

just do it

java多线程中断学习

来至《java多线程设计模式》

1.wait

   (1)调用wait方法必须先获得对象实例的锁;

   (2)可以再synchronized方法中,或synchronized块中或两者调用的别的方法中;

   (3)执行wait方法的线程会进入obj的wait set里面,进入之后就已经释放obj的锁;

   (4)被notify或notifyAll所唤醒的线程会前进到wait的下一个语句。

2.nofify和notifyAll

  (1)从obj的wait set中唤醒一个或所有线程(它们试图去获取obj的锁),但是唤醒它(们)之后,该线程仍未释放该锁

  (2)wait,notify,notifyAll为object类的方法,对实例的wait set进行操作。

3.sleep

  (1)为线程类方法,让线程进入阻塞状态,得不到CPU时间,时间一过重新进入可执行状态。但sleep方法不会释放对象的锁。

  (2)只能控制当前正在运行的线程。

4.yield

  (1)暂停当前正在执行的线程对象,并执行其他线程,让当前运行的线程回到可运行状态,并允许具有相同优先级的其他线程获得运行机会。

  (2)但它可能未让步而重新被调度程序选中。

5.join

  (1)让一个线程B加入到另一个线程A的尾部。

  (2)A执行完毕之前,B不能工作。

 

二、调用interrupt()的影响:

1.对sleep

   任何线程在任何时刻都可以调用其他线程的interrupt方法,被interrupt后放弃暂停状态,抛出异常。

2.对wait

  若obj已经在wait set中,interrupt方法会使线程重新获得锁再抛出异常,若未能获得锁定,则无法抛出异常。

  执行interrupt时无需获得对该线程的锁定。

3.join

  调用joion方法,无需获得锁定,马上跳到catch块里。

 

三、调用interrupt方法不一定会抛出interruptException:

   (1)若调用时,不是在执行sleep/wait/join则不会抛出异常,只是改变中断状态;

   (2)若调用时,是在执行sleep/wait/join则抛出异常。

 

  //  作业
    private void doWork() throws InterruptedException {
        counter++;
        System.out.println("doWork: counter = " + counter);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
        }
    }

以上若调用interrupt则无法中断。

System.out.println("main: shutdownRequest");
            t.shutdownRequest();

必须如下:

// 作业
    private void doWork() throws InterruptedException {
        counter++;
        System.out.println("doWork: counter = " + counter);
        Thread.sleep(500);
    }

则可以正常终止。

在调用doWork的地方进行捕获:

  // 动作
    public void run() {
        try {
            while (!isInterrupted()) {
                doWork();
            }
        } catch (InterruptedException e) {
        } finally {
            doShutdown();
        }
    }
 // 终止请求
    public void shutdownRequest() {
        interrupt();
    }
 

上面那个捕获异常之后没有处理,所以在run里面无法捕获,无法执行doShutdown方法来停止。

 

对比:

  public synchronized Request getRequest() throws InterruptedException {
        while (queue.size() <= 0) {
            wait();
        }
        return (Request)queue.removeFirst();
    }

这里抛出异常,同时在调用的地方进行捕获,并且退出run

public void run() {
        try {
            for (int i = 0; i < 10000; i++) {
                Request request = new Request("No." + i);
                System.out.println(Thread.currentThread().getName() + " requests " + request);
                requestQueue.putRequest(request);
                Thread.sleep(random.nextInt(1000));
            }
        } catch (InterruptedException e) {
        }
    }

调用时,是直接interrupt:

   //呼叫interrupt方法
        System.out.println("***** calling interrupt *****");
        alice.interrupt();
        bobby.interrupt();

posted on 2009-05-07 09:07  cxccbv  阅读(354)  评论(0)    收藏  举报

导航