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();
浙公网安备 33010602011771号