java 同步块 抛出异常_不把 wait 放在同步块中,为啥这种情况不会抛出 IllegalMonitorStateException?...

这是一个来自 Java 编程思想的例子,它只是想表达 sleep 的线程可中断,但同步 IO 等待资源,或同步获得锁失败的线程,是不可同步的。

//: concurrency/Interrupting.java

// Interrupting a blocked thread.

import java.util.concurrent.*;

import java.io.*;

import static net.mindview.util.Print.*;

class SleepBlocked implements Runnable {

public void run() {

try {

TimeUnit.SECONDS.sleep(100);

} catch(InterruptedException e) {

print("InterruptedException");

}

print("Exiting SleepBlocked.run()");

}

}

class IOBlocked implements Runnable {

private InputStream in;

public IOBlocked(InputStream is) { in = is; }

public void run() {

try {

print("Waiting for read():");

in.read();

} catch(IOException e) {

if(Thread.currentThread().isInterrupted()) {

print("Interrupted from blocked I/O");

} else {

throw new RuntimeException(e);

}

}

print("Exiting IOBlocked.run()");

}

}

class SynchronizedBlocked implements Runnable {

public synchronized void f() {

while(true) // Never releases lock

Thread.yield();

}

public SynchronizedBlocked() {

new Thread() {

public void run() {

f(); // Lock acquired by this thread

}

}.start();

}

public void run() {

print("Trying to call f()");

f();

print("Exiting SynchronizedBlocked.run()");

}

}

public class Interrupting {

private static ExecutorService exec =

Executors.newCachedThreadPool();

static void test(Runnable r) throws InterruptedException{

Future> f = exec.submit(r);

TimeUnit.MILLISECONDS.sleep(100);

print("Interrupting " + r.getClass().getName());

f.cancel(true); // Interrupts if running

print("Interrupt sent to " + r.getClass().getName());

}

public static void main(String[] args) throws Exception {

test(new SleepBlocked());

test(new IOBlocked(System.in));

test(new SynchronizedBlocked());

test(new Runnable() { //自己写的测试线程

@Override

public void run () {

System.out.println("1 start run");

try {

new Object().wait(); //这句不抛异常,为什么?

} catch (InterruptedException e) {

System.out.println("1 catch InterruptedException");

e.printStackTrace();

}

System.out.println("1 exit run");

}

});

TimeUnit.SECONDS.sleep(3);

print("Aborting with System.exit(0)");

new Object().wait(); //这句抛异常

System.exit(0); // ... since last 2 interrupts failed

}

}

打印结果:

Interrupting SleepBlocked

Interrupt sent to SleepBlocked

InterruptedException

Exiting SleepBlocked.run()

Waiting for read():

Interrupting IOBlocked

Interrupt sent to IOBlocked

Trying to call f()

Interrupting SynchronizedBlocked

Interrupt sent to SynchronizedBlocked

1 start run

Interrupting Interrupting$1

Interrupt sent to Interrupting$1 //而且看起来,中断也没起作用?(如果有作用,之后应该出现这个线程的打印结果)

Aborting with System.exit(0)

Exception in thread "main" java.lang.IllegalMonitorStateException

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:502)

at Interrupting.main(Interrupting.java:92)

我知道 wait 正确用法是在同步方法或同步块中使用,

所以现在问题有 2 个,

为啥主函数的 new Object().wait();抛 IllegalMonitorStateException 异常,我自创的线程却没有抛出 IllegalMonitorStateException 异常呢?

从打印结果,我那个线程真的 wait 了(因为只打印出来一句)。但为啥中断它时,还是没有反应呢?

test(new Runnable() {

@Override

public void run () {

synchronized(this) {

System.out.println("1 start run");

try {

wait();

} catch (InterruptedException e) {

System.out.println("1 catch InterruptedException");

e.printStackTrace();

}

System.out.println("1 exit run");

}

}

});

然后我试了上面这个版本的,打印结果如下:

Interrupting SleepBlocked

Interrupt sent to SleepBlocked

InterruptedException

Exiting SleepBlocked.run()

Waiting for read():

Interrupting IOBlocked

Interrupt sent to IOBlocked

Trying to call f()

Interrupting SynchronizedBlocked

Interrupt sent to SynchronizedBlocked

1 start run

Interrupting Interrupting$1

Interrupt sent to Interrupting$1

1 catch InterruptedException

java.lang.InterruptedException

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:502)

at Interrupting$1.run(Interrupting.java:75)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)

1 exit run

Aborting with System.exit(0)

Exception in thread "main" java.lang.IllegalMonitorStateException

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:502)

at Interrupting.main(Interrupting.java:86)

所以,wait 之前是获得锁的情况,才可以被中断呗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值