1、线程阻塞
一个线程进入阻塞状态可能的原因:
通过调用sleep(millseconds)使任务进入休眠状态;
1 2 3 4 5 6 7 8 9 10 11 12
| class Demo1 implements Runnable throws InterruptedException{ public void run(){ Thread.sleep(1000); } } ②通过调用wait()使线程挂起,直到线程获取notify()/notifyAll()消息,(或者在Java SE5中java.util.concurrent类库中等价的signal()/signalAll()消息),线程才会进入就绪状态; class Demo2 implements Runnable{ public void run(){ Thread.await(); Thread.notify(); } }
|
任务在等待某个输入 / 输出流的完成;
1 2 3 4 5 6
| class Demo3 implements Runnable throws InterruptedException{ private InputStream in; public void run(){ in.read(); } }
|
任务试图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了该锁;
1 2 3 4 5 6 7
| class Demo4 implements Runnable{ public synchronized void method1(){ } public synchronized void method2(){ } public void run(){ method1(); } }
|
2、线程中断的方法
Thread类包含interrupt()方法,用于终止阻塞任务;
1)中断①②类线程休眠,挂起阻塞的方法
1.直接使用Thread.interrupt();
1 2 3 4
| main(){ Thread t = new Thread(new Demo1()); t.interrupt(); }
|
2.使用Executor线程池,中断线程池中的所有线程;
1 2 3 4 5 6
| main(){ ExecutorService exec = Executors.newCachedThreadPool(); for(int i=0;i<5;i++) exec.execute(new Demo1()) exec.shutdownNow(); }
|
3.使用Executor线程池,中断线程池中单个阻塞的线程;
1 2 3 4 5
| main(){ ExecutorService exec = Executors.newCachedThreadPool(); Futrue<?> f = exec.submit(new Demo1()); f.interrupt(); }
|
//中断后的清除代码放置在InterruptedException异常的catch捕获的代码块中
2)中断③类I/O阻塞的方法
使用Thread.iterrupt方法无法中断I/O阻塞,这对于基于Web的程序是很不利的;
有一种解决方法:关闭任务在其上发生阻塞的底层资源;
1 2 3 4 5 6 7 8 9 10 11 12
| main(){ ExecutorService exec = Executors.newCachedThreadPool(); ServerSocket server = new ServerSocket(8080); InputStream socketInput = new Socket("localhost",8080) exec.execute(socketInput); exec.execute(Sytsem.in);
socketInput.close(); in.close(); exec.shutdownNow(); }
|
java.nio类库提供了更加人性化的I/O中断,被阻塞的nio通道会自动地响应中断;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Demo impelenets Runnable{ private final SocketChannel sc; public Demo(SocketChannel sc){ this.sc = sc;} public void run(){ try{ sc.read(ByteBuffer.allocate(1)); }catch(CloseByInteruptedException e1){ }catch(AsyncronousCloseException e2){ }catch(IOException e3){ } } } public Test { public static void main(){ ExecutorService exec = Executors.newCachedThreadPool(); ServerSocket server = new ServerSocket(8080); InetSocketAddress isa = new InetSocketAddress("localhost",8080); SocketChannel sc1 = new SocketChannel.open(isa); SocketChannel sc2 = new SocketChannel.open(isa); exec.execute(new Demo(sc1)); Future<?> f = exec.submit(new Demo(sc2)); f.cancel(true); exec.shutdownNow(); sc1.close(); sc2.close(); } }
|
3)中断④类被互斥阻塞的线程
使用Thread.iterrupt方法无法中断互斥类线程,
解决方式1:可以使用ReentrantLock显式加锁,在JavaSE5中引入的新特性,ReentrantLock上阻塞的任务可以被中断;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Task imlements Runnable{ private Lock lock = new ReentrantLock(); public void run(){ lock.lock(); try{ while(true) }catch(InterruptedExcpetion e){ System.out.println("The Task is interrupted!"); }finally{ lock.unlock(); } } public void main(){ Thread t = new Thread(new Task()); t.start(); t.interrupt(); } }
|
解决方式2:使用一个while(!Thread.interrupted())包裹同步的代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Task impelments Runnable{ private synchronized void method1(){ } public void run(){ try{ whlie(!Thread.interrupted()) method1(); }catch(InteruptedException e){ } } public static void main(){ ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new Task()); exec.shutdownNow();
} }
|