第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

深入分析Java線程中斷機(jī)制

標(biāo)簽:
Java

如果interrutp方法能够中断线程,那么在打印了is interrupt…….之后应该是没有log了,我们看看执行结果吧

is start.......
我没有种中断
我没有种中断
我没有种中断
我没有种中断
我没有种中断is interrupt.......
我没有种中断
我没有种中断
我没有种中断
我没有种中断
我没有种中断
....

通过结果可以发现子线程并没有中断

所以 Thread.interrupt() 方法并不能中断线程,该方法仅仅告诉线程外部已经有中断请求,至于是否中断还取决于线程自己。在Thread类中除了interrupt() 方法还有另外两个非常相似的方法:interrupted 和 isInterrupted 方法,下面来对这几个方法进行说明:

处理线程中断的常用方法

设置取消标记

还是用上面的例子,只不过做了些修改

public static void main(String[] args) {
    NRunnable run=new NRunnable();
    Thread t=new Thread(run);
    t.start();
    System.out.println("is start.......");    try {
      Thread.sleep(3000);
    } catch (InterruptedException e) {

    }
    run.cancel();
    System.out.println("cancel ..."+System.currentTimeMillis());
  }  public static class NRunnable implements Runnable
  {    public boolean isCancel=false;    @Override
    public void run() {      while(!isCancel)
      {
        System.out.println("我没有种中断");        try {
          Thread.sleep(10000);
        } catch (InterruptedException e) {

        }
      }
      System.out.println("我已经结束了..."+System.currentTimeMillis());
    }    public void cancel()
    {      this.isCancel=true;
    }

  }

执行结果如下:

is start.......
我没有种中断cancel ...1438396915809我已经结束了...1438396922809

通过结果,我们发现线程确实已经中断了,但是细心的同学应该发现了一个问题,调用cancel方法和最后线程执行完毕之间隔了好几秒的时间,也就是说线程不是立马中断的,我们下面来分析一下原因:

子线程退出的条件是while循环结束,也就是cancel标示设置为true,但是当我们调用cancel方法将calcel标记设置为true时,while循环里面有一个耗时操作(sleep方法模拟),只有等待耗时操作执行完毕后才会去检查这个标记,所以cancel方法和线程退出中间有时间间隔。

通过interrupt 和 isinterrupt 方法来中断线程

public static void main(String[] args) {
    Thread t=new NThread();
    t.start();
    System.out.println("is start.......");    try {
      Thread.sleep(3000);
    } catch (InterruptedException e) {

    }
    System.out.println("start interrupt..."+System.currentTimeMillis());
    t.interrupt();
    System.out.println("end interrupt ..."+System.currentTimeMillis());
  }  public static class NThread extends Thread
  {

    @Override    public void run() {      while(!this.isInterrupted())
      {
        System.out.println("我没有种中断");        try {
          Thread.sleep(10000);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
        }
      }
      System.out.println("我已经结束了..."+System.currentTimeMillis());
    }

  }
}

运行结果如下:

is start.......
我没有种中断start interrupt...1438398800110我已经结束了...1438398800110end interrupt ...1438398800110

这次是立马中断的,但是这种方法是由局限性的,这种方法仅仅对于会抛出InterruptedException 异常的任务时有效的,比如java中的sleep、wait 等方法,对于不会抛出这种异常的任务其效果其实和第一种方法是一样的,都会有延迟性,这个例子中还有一个非常重要的地方就是cache语句中,我们调用了Thread.currentThread().interrupt() 我们把这句代码去掉,运行你会发现这个线程无法终止,因为在抛出InterruptedException 的同时,线程的中断标志被清除了,所以在while语句中判断当前线程是否中断时,返回的是false.针对InterruptedException 异常,我想说的是:一定不能再catch语句块中什么也不干,如果你实在不想处理,你可以将异常抛出来,让调用抛异常的方法也成为一个可以抛出InterruptedException 的方法,如果自己要捕获此异常,那么最好在cache语句中调用 Thread.currentThread().interrupt(); 方法来让高层只要中断请求并处理该中断。

对于上述两种方法都有其局限性,第一种方法只能处理那种工作量不大,会频繁检查循环标志的任务,对于第二种方法适合用于抛出InterruptedException的代码。也就是说第一种和第二种方法支持的是支持中断的线程任务,那么不支持中断的线程任务该怎么做呢。

例如 如果一个线程由于同步进行I/O操作导致阻塞,中断请求不会抛出InterruptedException ,我们该如何中断此线程呢。

处理不支持中断的线程中断的常用方法

改写线程的interrupt方法

public static class ReaderThread extends Thread
 {   public static final int BUFFER_SIZE=512;
   Socket socket;
   InputStream is;   public ReaderThread(Socket socket) throws IOException   {     this.socket=socket;
     is=this.socket.getInputStream();
   }   @Override
  public void interrupt() {     try
     {
       socket.close();
     }catch(IOException e)
     {

     }finally
     {       super.interrupt();
     }    super.interrupt();
  }   @Override
  public void run() {     try
     {       byte[]buf=new byte[BUFFER_SIZE];       while(true)
       {         int count=is.read(buf);         if(count<0)           break;         else if(count>0)
         {

         }
       }
     }catch(IOException e)
     {

     }
  }
 }
}

例如在上面的例子中,改写了Thread的interrupt 方法,当调用interrupt 方法时,会关闭socket,如果此时read方法阻塞,那么会抛出IOException 此时线程任务也就结束了。

以上方法是通过改写线程的interrupt 方法实现,那么对于使用线程池的任务该怎么中断呢。

改写线程池的newTaskFor方法

通常我们向线程池中加入一个任务采用如下形式:

Future<?> future=executor.submit(new Runnable(){      @Override
      public void run() {

      }
    });

取消任务时,调用的是future的cancel方法,其实在cancel方法中调用的是线程的interrupt方法。所以对于不支持中断的任务cancel也是无效的,下面我们看看submit方法里面干了上面吧

    public Future<?> submit(Runnable task) {        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);        return ftask;
    }

这里调用的是AbstractExecutorService 的newTaskFor方法,那么我们能不能改写ThreadPoolExecutor的newTaskFor方法呢,接下来看我在处理吧

定义一个基类,所有需要取消的任务继承这个基类

public interface CancelableRunnable<T> extends Runnable {  public void cancel();  public RunnableFuture<T> newTask();

}

将上面的ReaderThread改为继承这个类

 public static class ReaderThread implements CancelableRunnable<Void>  {    public static final int BUFFER_SIZE=512;
    Socket socket;
    InputStream is;    public ReaderThread(Socket socket) throws IOException    {      this.socket=socket;
      is=this.socket.getInputStream();
    }    @Override
   public void run() {      try
      {        byte[]buf=new byte[BUFFER_SIZE];        while(true)
        {          int count=is.read(buf);          if(count<0)            break;          else if(count>0)
          {

          }
        }
      }catch(IOException e)
      {

      }
   }    @Override
    public void cancel() {      try {
        socket.close();
      } catch (IOException e) {

      }
    }    @Override
    public RunnableFuture<Void> newTask() {      return new FutureTask<Void>(this,null)
          {            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {              return super.cancel(mayInterruptIfRunning);              if(ReaderThread.this instanceof CancelableRunnable))
              {
                ((CancelableRunnable)(ReaderThread.this)).cancel();
              }else
              {                super.cancel(mayInterruptIfRunning);
              }
            }
          };

    }
 }

当你调用future的cancel的方法时,它会关闭socket,最终导致read方法异常,从而终止线程任务。


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消