疯狂java~~

最近有点小忙.没弄博客了..

这次讲的是interrupt方法特点.自习都上得比较长了.╮(╯▽╰)╭


设想这样的情景:我们的应用在某一个时间段内,需要一个子线程不停的在后台运行,这可能是一个下载过程,是一个对服务端socket的监听,也可能是一个绘图的计算过程。当我们想要终止线程的时候,我们会怎样做呢?是设定一个标志变量来控制跳出循环?还是使用thread.stop()?又或者是设置thread = null?
  有的时候我们需要一种规范的思路,使用规范的方法来解决一类问题。
  我们首先要明白,线程终止的条件,有三种情况:
  1.当线程的run方法执行方法体中最后一条语句后。
  2.当执行retutrn语句返回时。
  3.当出现了在方法中没有捕获的异常时。
  在Java的早期版本中,还有一个stop方法,其他线程可以调用它终止线程,但是这个方法已经被弃用了,所以还在用的同学就不要继续用了。
  我们的正确思路是,使用interrupt方法来终止我们的线程。
  首先要理解interrupt方法做了什么:每一个线程都有一个中断状态,这是一个boolean标志,当线程调用了interrupt方法时,这个中断状态就会被置位。如果我们要检查中断状态,可以使用Thread.currentThread()。isInterrupted()来获得是否中断。
  但是如果线程被阻塞了(sleep or wait),当我们调用了interrupt方法的时候,就会产生InterruptedException异常。这是我们可以利用的地方。
  同样的,如果中断状态先被置位了,然后我们调用了sleep方法,线程不会休眠,相反,它将清除中断状态,然后抛出InterruptedException.
  我们调用了interrupt并不意味着线程会终止,线程是否会终止,以及会如何继续,是程序员来控制的。
  在本文中我们将会讨论终止线程的规范用法,然后在一个例子中实际应用,在这个例子中我们模拟了文件拷贝和游戏绘图两种情形。做出的效果如下图所示,点击start后上方进度条会显示文件拷贝的进度,点击end则会停止拷贝。点击draw会在画面中不停绘制各种各样的矩形,点击stop则会停止绘制。


  首先我们来看两种情形的后台线程写法:
  public void run() {
  try{
  …
  while(!Thread.currentThread.isInterrupted() && more work to do)
  {
  do more work
  }
  }
  catch(InterruptedException)
  {
  //thread was interrupted during sleep or wait
  }
  finally
  {
  cleanup, if required
  }
  //exiting the run method terminates the thread }
  public void run() {
  try{
  …
  while( more work to do)
  {
  do more work
  Thread.sleep(delay);
  }
  }
  catch(InterruptedException)
  {
  //thread was interrupted during sleep or wait
  }
  finally
  {
  cleanup, if required
  }
  //exiting the run method terminates the thread }
  第一种写法适用于后台下载,文件拷贝以及类似情形,第二种写法适合游戏画面刷新或者类似情形。
  第一种写法利用了interrupt方法,作为终止的请求,使得循环跳出,run方法执行完毕。而第二种方法则是利用当线程sleep的时候调用interrupt会抛出InterruptedException从而跳出了循环进而线程执行到结束。
  事实上这两种写法的区别就在于第二种使用了sleep.
  在我们的使用示例中,对应这两种方法的使用代码如下:
  这一段是实现文件拷贝的:
  private class CopyRunnable implements Runnable {
  @Override
  public void run() {
  File fromFile = new File(Environment.getExternalStorageDirectory()
  .getAbsolutePath() + "/abc.exe");
  long fileLength = fromFile.length();
  long copyedLength = 0;
  File toFile = new File(Environment.getExternalStorageDirectory()
  .getAbsolutePath() + "/abc_.exe");
  if (toFile.exists()) {
  toFile.delete();
  }
  try {
  FileInputStream fileInputStream = new FileInputStream(fromFile);
  FileOutputStream fileOutputStream = new FileOutputStream(
  toFile, true);
  byte[] buffer = new byte[2048];
  int readLength = 0;
  while (!Thread.currentThread()。isInterrupted()
  && (readLength = fileInputStream.read(buffer)) != -1) {
  fileOutputStream.write(buffer, 0, buffer.length);
  copyedLength += readLength;
  int progress = (int)
  ((float) copyedLength / fileLength * 100);
  handler.obtainMessage(0, progress, 0)。sendToTarget();
  }
  } catch (FileNotFoundException e) {
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  } finally {
  handler.obtainMessage(1)。sendToTarget();
  }
  }
  }
  这一段是实现矩形绘图的:
  private class DrawRunnable implements Runnable {
  @Override
  public void run() {
  try {
  while (true) {
  long beginTime = System.currentTimeMillis();
  paint.setColor(getColor());
  getCoor();
  postInvalidate();
  long endTime = System.currentTimeMillis();
  if (endTime - beginTime < 150) {
  Thread.sleep(150 - (endTime - beginTime));
  }
  }
  } catch (InterruptedException e) {
  e.printStackTrace();
  } finally {
  }
  }
  }
  实际上这两种写法都是利用了interrupt方法的特点,通过线程的中断置位或者异常抛出来跳出循环进而终结线程。如果对这段代码感兴趣,可以到文章最后下载代码。
  最后做一下方法总结:
  void interrupt()
  向线程发送中断请求。线程的中断状态将被设置为true.如果目前该线程被一个sleep调用阻塞,那么,InterruptedException异常被抛出。
  static boolean interrupted()
  测试当前线程(即正在执行这一命令的线程)是否被中断,注意,这是一个静态方法。这一调用会产生副作用,它将当前线程的中断状态设置为false.
  boolean isInterrupted()
  测试线程是否被中断。不像静态的中断方法,这一调用不会改变线程的中断状态。
  static Thread currentThread()
  返回代表当前执行线程的Thread对象。

   还是要经常的去敲代码比较好.不容老师讲的消化不了~~~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值