程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java多線程編程中線程的啟動、中止或終止操作

詳解Java多線程編程中線程的啟動、中止或終止操作

編輯:關於JAVA

詳解Java多線程編程中線程的啟動、中止或終止操作。本站提示廣大學習愛好者:(詳解Java多線程編程中線程的啟動、中止或終止操作)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java多線程編程中線程的啟動、中止或終止操作正文


線程啟動:
1.start() 和 run()的差別解釋
start() : 它的感化是啟動一個新線程,新線程會履行響應的run()辦法。start()不克不及被反復挪用。
run() : run()就和通俗的成員辦法一樣,可以被反復挪用。零丁挪用run()的話,會在以後線程中履行run(),而其實不會啟動新線程!
上面以代碼來停止解釋。

class MyThread extends Thread{ 
  public void run(){
    ...
  } 
};
MyThread mythread = new MyThread();

mythread.start()會啟動一個新線程,並在新線程中運轉run()辦法。
而mythread.run()則會直接在以後線程中運轉run()辦法,其實不會啟動一個新線程來運轉run()。

2.start() 和 run()的差別示例
上面,經由過程一個簡略示例演示它們之間的差別。源碼以下:

// Demo.java 的源碼
class MyThread extends Thread{
  public MyThread(String name) {
    super(name);
  }

  public void run(){
    System.out.println(Thread.currentThread().getName()+" is running");
  } 
};

public class Demo { 
  public static void main(String[] args) { 
    Thread mythread=new MyThread("mythread");

    System.out.println(Thread.currentThread().getName()+" call mythread.run()");
    mythread.run();

    System.out.println(Thread.currentThread().getName()+" call mythread.start()");
    mythread.start();
  } 
}

運轉成果:

main call mythread.run()
main is running
main call mythread.start()
mythread is running

成果解釋:
(1) Thread.currentThread().getName()是用於獲得“以後線程”的名字。以後線程是斧正在cpu中調劑履行的線程。
(2) mythread.run()是在“主線程main”中挪用的,該run()辦法直接運轉在“主線程main”上。
(3) mythread.start()會啟動“線程mythread”,“線程mythread”啟動以後,會挪用run()辦法;此時的run()辦法是運轉在“線程mythread”上。

線程的中止和終止

1、線程中止:interrupt()
interrupt()的感化是中止本線程。
本線程中止本身是被許可的;其它線程挪用本線程的interrupt()辦法時,會經由過程checkAccess()檢討權限。這有能夠拋出SecurityException異常。
假如本線程是處於壅塞狀況:挪用線程的wait(), wait(long)或wait(long, int)會讓它進入期待(壅塞)狀況,或許挪用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入壅塞狀況。若線程在壅塞狀況時,挪用了它的interrupt()辦法,那末它的“中止狀況”會被消除而且會收到一個InterruptedException異常。例如,線程經由過程wait()進入壅塞狀況,此時經由過程interrupt()中止該線程;挪用interrupt()會立刻將線程的中止標志設為“true”,然則因為線程處於壅塞狀況,所以該“中止標志”會立刻被消除為“false”,同時,會發生一個InterruptedException的異常。
假如線程被壅塞在一個Selector選擇器中,那末經由過程interrupt()中止它時;線程的中止標志會被設置為true,而且它會立刻從選擇操作中前往。
假如不屬於後面所說的情形,那末經由過程interrupt()中止線程時,它的中止標志會被設置為“true”。
中止一個“已終止的線程”不會發生任何操作。

2、線程終止
Thread中的stop()和suspend()辦法,因為固有的不平安性,曾經建議不再應用!
上面,我先分離評論辯論線程在“壅塞狀況”和“運轉狀況”的終止方法,然後再總結出一個通用的方法。
1. 終止處於“壅塞狀況”的線程
平日,我們經由過程“中止”方法終止處於“壅塞狀況”的線程。
當線程因為被挪用了sleep(), wait(), join()等辦法而進入壅塞狀況;若此時挪用線程的interrupt()將線程的中止標志設為true。因為處於壅塞狀況,中止標志會被消除,同時發生一個InterruptedException異常。將InterruptedException放在恰當的為止就可以終止線程,情勢以下:

@Override
public void run() {
  try {
    while (true) {
      // 履行義務...
    }
  } catch (InterruptedException ie) { 
    // 因為發生InterruptedException異常,加入while(true)輪回,線程終止!
  }
}

解釋:在while(true)中赓續的履行義務,當線程處於壅塞狀況時,挪用線程的interrupt()發生InterruptedException中止。中止的捕捉在while(true)以外,如許就加入了while(true)輪回!
留意:對InterruptedException的捕捉務普通放在while(true)輪回體的裡面,如許,在發生異常時就加入了while(true)輪回。不然,InterruptedException在while(true)輪回體以內,就須要額定的添加加入處置。情勢以下:

@Override
public void run() {
  while (true) {
    try {
      // 履行義務...
    } catch (InterruptedException ie) { 
      // InterruptedException在while(true)輪回體內。
      // 當線程發生了InterruptedException異常時,while(true)仍能持續運轉!須要手動加入
      break;
    }
  }
}

解釋:下面的InterruptedException異常的捕捉在whle(true)以內。當發生InterruptedException異常時,被catch處置以外,依然在while(true)輪回體內;要加入while(true)輪回體,須要額定的履行加入while(true)的操作。
2. 終止處於“運轉狀況”的線程
平日,我們經由過程“標志”方法終止處於“運轉狀況”的線程。個中,包含“中止標志”和“額定添加標志”。
(1) 經由過程“中止標志”終止線程。
情勢以下:

@Override
public void run() {
  while (!isInterrupted()) {
    // 履行義務...
  }
}

解釋:isInterrupted()是斷定線程的中止標志是否是為true。當線程處於運轉狀況,而且我們須要終止它時;可以挪用線程的interrupt()辦法,應用線程的中止標志為true,即isInterrupted()會前往true。此時,就會加入while輪回。
留意:interrupt()其實不會終止處於“運轉狀況”的線程!它會將線程的中止標志設為true。
(2) 經由過程“額定添加標志”。
情勢以下:

private volatile boolean flag= true;
protected void stopTask() {
  flag = false;
}

@Override
public void run() {
  while (flag) {
    // 履行義務...
  }
}

解釋:線程中有一個flag標志,它的默許值是true;而且我們供給stopTask()來設置flag標志。當我們須要終止該線程時,挪用該線程的stopTask()辦法便可以讓線程加入while輪回。
留意:將flag界說為volatile類型,是為了包管flag的可見性。即其它線程經由過程stopTask()修正了flag以後,本線程能看到修正後的flag的值。
綜合線程處於“壅塞狀況”和“運轉狀況”的終止方法,比擬通用的終止線程的情勢以下:

@Override
public void run() {
  try {
    // 1. isInterrupted()包管,只需中止標志為true就終止線程。
    while (!isInterrupted()) {
      // 履行義務...
    }
  } catch (InterruptedException ie) { 
    // 2. InterruptedException異常包管,當InterruptedException異常發生時,線程被終止。
  }
}

3. 終止線程的示例
interrupt()經常被用來終止“壅塞狀況”線程。參考上面示例:

// Demo1.java的源碼
class MyThread extends Thread {

  public MyThread(String name) {
    super(name);
  }

  @Override
  public void run() {
    try { 
      int i=0;
      while (!isInterrupted()) {
        Thread.sleep(100); // 休眠100ms
        i++;
        System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); 
      }
    } catch (InterruptedException e) { 
      System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); 
    }
  }
}

public class Demo1 {

  public static void main(String[] args) { 
    try { 
      Thread t1 = new MyThread("t1"); // 新建“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線程休眠300ms,然後主線程給t1發“中止”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線程休眠300ms,然後檢查t1的狀況。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運轉成果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

成果解釋:
(1) 主線程main中經由過程new MyThread("t1")創立線程t1,以後經由過程t1.start()啟動線程t1。
(2) t1啟動以後,會赓續的檢討它的中止標志,假如中止標志為“false”;則休眠100ms。
(3) t1休眠以後,會切換到主線程main;主線程再次運轉時,會履行t1.interrupt()中止線程t1。t1收到中止指令以後,會將t1的中止標志設置“false”,並且會拋出InterruptedException異常。在t1的run()辦法中,是在輪回體while以外捕捉的異常;是以輪回被終止。
我們對下面的成果停止小小的修正,將run()辦法中捕捉InterruptedException異常的代碼塊移到while輪回體內。

// Demo2.java的源碼
class MyThread extends Thread {

  public MyThread(String name) {
    super(name);
  }

  @Override
  public void run() {
    int i=0;
    while (!isInterrupted()) {
      try {
        Thread.sleep(100); // 休眠100ms
      } catch (InterruptedException ie) { 
        System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); 
      }
      i++;
      System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); 
    }
  }
}

public class Demo2 {

  public static void main(String[] args) { 
    try { 
      Thread t1 = new MyThread("t1"); // 新建“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線程休眠300ms,然後主線程給t1發“中止”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線程休眠300ms,然後檢查t1的狀況。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運轉成果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...

成果解釋:
法式進入了逝世輪回!
為何會如許呢?這是由於,t1在“期待(壅塞)狀況”時,被interrupt()中止;此時,會消除中止標志[即isInterrupted()會前往false],並且會拋出InterruptedException異常[該異常在while輪回體內被捕捉]。是以,t1天經地義的會進入逝世輪回了。
處理該成績,須要我們在捕捉異常時,額定的停止加入while輪回的處置。例如,在MyThread的catch(InterruptedException)中添加break 或 return就可以處理該成績。
上面是經由過程“額定添加標志”的方法終止“狀況狀況”的線程的示例:

// Demo3.java的源碼
class MyThread extends Thread {

  private volatile boolean flag= true;
  public void stopTask() {
    flag = false;
  }

  public MyThread(String name) {
    super(name);
  }

  @Override
  public void run() {
    synchronized(this) {
      try {
        int i=0;
        while (flag) {
          Thread.sleep(100); // 休眠100ms
          i++;
          System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i); 
        }
      } catch (InterruptedException ie) { 
        System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException."); 
      }
    } 
  }
}

public class Demo3 {

  public static void main(String[] args) { 
    try { 
      MyThread t1 = new MyThread("t1"); // 新建“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動“線程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線程休眠300ms,然後主線程給t1發“中止”指令。
      Thread.sleep(300);
      t1.stopTask();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線程休眠300ms,然後檢查t1的狀況。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運轉成果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved