Java线程阻塞与中断

线程阻塞和中断



1、线程阻塞
一个线程进入 阻塞状态可能的原因:
①通过调用sleep(millseconds)使任务进入 休眠状态
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();
     }
}
③任务在等待某个 输入 / 输出流的完成;
class Demo3 implements Runnable throws InterruptedException{
     private InputStream in;
     public void run(){
          in.read();
     }
}
④任务试图在某个对象上调用其 同步控制方法,但是对象锁不可用,因为另一个任务已经获取了该锁;
class Demo4 implements Runnable{
     public synchronized void method1(){     }
     public synchronized void method2(){     }
     public void run(){
          method1();
     }
}


2、线程中断的方法
Thread类包含interrupt()方法,用于终止阻塞任务;

1)中断①②类线程休眠,挂起阻塞的方法
1.直接使用Thread.interrupt();
main(){
     Thread t = new Thread(new Demo1());
     t.interrupt();
}
2.使用Executor线程池,中断线程池中的所有线程;
main(){
     ExecutorService exec = Executors.newCachedThreadPool();
     for(int i=0;i<5;i++)
          exec.execute(new Demo1())
      exec.shutdownNow();
}
3.使用Executor线程池,中断线程池中单个阻塞的线程;
main(){
     ExecutorService exec = Executors.newCachedThreadPool();
     Futrue f = exec.submit(new Demo1());
     f.interrupt();
}

//中断后的清除代码放置在InterruptedException异常的catch捕获的代码块中


2)中断③类I/O阻塞的方法
使用Thread.iterrupt方法无法中断I/O阻塞,这对于基于Web的程序是很不利的;
①有一种解决方法: 关闭任务在其上发生阻塞的底层资源;
main(){
     ExecutorService exec = Executors.newCachedThreadPool();
     ServerSocket server = new ServerSocket(8080);
     InputStream socketInput = new Socket("localhost",8080)
     exec.execute(socketInput);
      exec.execute(Sytsem.in);
     //exec.shutdownNow(); 无法中断2个线程;

     socketInput.close();
     in.close();
     exec.shutdownNow();
}

②java.nio类库提供了更加人性化的I/O中断, 被阻塞的nio通道会自动地响应中断;
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);  //可以终止sc1通道所在的线程;
          exec.shutdownNow();  //可以终止exec线程池内所有的线程;
          sc1.close();
          sc2.close();
     }
}

3)中断④类被互斥阻塞的线程
使用Thread.iterrupt方法无法中断互斥类线程,
解决方式1可以使用ReentrantLock显式加锁,在JavaSE5中引入的新特性,ReentrantLock上阻塞的任务可以被中断;
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())包裹同步的代码块
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();  //线程被打断
          /*或 Thread t = new Thread(new Task());
               t.start();
               t.interrupt(); */
     }
}

你可能感兴趣的:(Java,Java,并发编程)