最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java多線(xiàn)程編程中線(xiàn)程的啟動(dòng)、中斷或終止操作

 更新時(shí)間:2016年07月02日 08:59:43   作者:skywangkw  
在Java中start和tun方法可用被用來(lái)啟動(dòng)線(xiàn)程,而用interrupt方法來(lái)中斷或終止線(xiàn)程,以下我們就來(lái)詳解Java多線(xiàn)程編程中線(xiàn)程的啟動(dòng)、中斷或終止操作

線(xiàn)程啟動(dòng):
1.start() 和 run()的區(qū)別說(shuō)明
start() : 它的作用是啟動(dòng)一個(gè)新線(xiàn)程,新線(xiàn)程會(huì)執(zhí)行相應(yīng)的run()方法。start()不能被重復(fù)調(diào)用。
run() : run()就和普通的成員方法一樣,可以被重復(fù)調(diào)用。單獨(dú)調(diào)用run()的話(huà),會(huì)在當(dāng)前線(xiàn)程中執(zhí)行run(),而并不會(huì)啟動(dòng)新線(xiàn)程!
下面以代碼來(lái)進(jìn)行說(shuō)明。

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

mythread.start()會(huì)啟動(dòng)一個(gè)新線(xiàn)程,并在新線(xiàn)程中運(yùn)行run()方法。
而mythread.run()則會(huì)直接在當(dāng)前線(xiàn)程中運(yùn)行run()方法,并不會(huì)啟動(dòng)一個(gè)新線(xiàn)程來(lái)運(yùn)行run()。

2.start() 和 run()的區(qū)別示例
下面,通過(guò)一個(gè)簡(jiǎn)單示例演示它們之間的區(qū)別。源碼如下:

// 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();
  } 
}

運(yùn)行結(jié)果:

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

結(jié)果說(shuō)明:
(1) Thread.currentThread().getName()是用于獲取“當(dāng)前線(xiàn)程”的名字。當(dāng)前線(xiàn)程是指正在cpu中調(diào)度執(zhí)行的線(xiàn)程。
(2) mythread.run()是在“主線(xiàn)程main”中調(diào)用的,該run()方法直接運(yùn)行在“主線(xiàn)程main”上。
(3) mythread.start()會(huì)啟動(dòng)“線(xiàn)程mythread”,“線(xiàn)程mythread”啟動(dòng)之后,會(huì)調(diào)用run()方法;此時(shí)的run()方法是運(yùn)行在“線(xiàn)程mythread”上。

線(xiàn)程的中斷和終止

一、線(xiàn)程中斷:interrupt()
interrupt()的作用是中斷本線(xiàn)程。
本線(xiàn)程中斷自己是被允許的;其它線(xiàn)程調(diào)用本線(xiàn)程的interrupt()方法時(shí),會(huì)通過(guò)checkAccess()檢查權(quán)限。這有可能拋出SecurityException異常。
如果本線(xiàn)程是處于阻塞狀態(tài):調(diào)用線(xiàn)程的wait(), wait(long)或wait(long, int)會(huì)讓它進(jìn)入等待(阻塞)狀態(tài),或者調(diào)用線(xiàn)程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會(huì)讓它進(jìn)入阻塞狀態(tài)。若線(xiàn)程在阻塞狀態(tài)時(shí),調(diào)用了它的interrupt()方法,那么它的“中斷狀態(tài)”會(huì)被清除并且會(huì)收到一個(gè)InterruptedException異常。例如,線(xiàn)程通過(guò)wait()進(jìn)入阻塞狀態(tài),此時(shí)通過(guò)interrupt()中斷該線(xiàn)程;調(diào)用interrupt()會(huì)立即將線(xiàn)程的中斷標(biāo)記設(shè)為“true”,但是由于線(xiàn)程處于阻塞狀態(tài),所以該“中斷標(biāo)記”會(huì)立即被清除為“false”,同時(shí),會(huì)產(chǎn)生一個(gè)InterruptedException的異常。
如果線(xiàn)程被阻塞在一個(gè)Selector選擇器中,那么通過(guò)interrupt()中斷它時(shí);線(xiàn)程的中斷標(biāo)記會(huì)被設(shè)置為true,并且它會(huì)立即從選擇操作中返回。
如果不屬于前面所說(shuō)的情況,那么通過(guò)interrupt()中斷線(xiàn)程時(shí),它的中斷標(biāo)記會(huì)被設(shè)置為“true”。
中斷一個(gè)“已終止的線(xiàn)程”不會(huì)產(chǎn)生任何操作。

二、線(xiàn)程終止
Thread中的stop()和suspend()方法,由于固有的不安全性,已經(jīng)建議不再使用!
下面,我先分別討論線(xiàn)程在“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,然后再總結(jié)出一個(gè)通用的方式。
1. 終止處于“阻塞狀態(tài)”的線(xiàn)程
通常,我們通過(guò)“中斷”方式終止處于“阻塞狀態(tài)”的線(xiàn)程。
當(dāng)線(xiàn)程由于被調(diào)用了sleep(), wait(), join()等方法而進(jìn)入阻塞狀態(tài);若此時(shí)調(diào)用線(xiàn)程的interrupt()將線(xiàn)程的中斷標(biāo)記設(shè)為true。由于處于阻塞狀態(tài),中斷標(biāo)記會(huì)被清除,同時(shí)產(chǎn)生一個(gè)InterruptedException異常。將InterruptedException放在適當(dāng)?shù)臑橹咕湍芙K止線(xiàn)程,形式如下:

@Override
public void run() {
  try {
    while (true) {
      // 執(zhí)行任務(wù)...
    }
  } catch (InterruptedException ie) { 
    // 由于產(chǎn)生InterruptedException異常,退出while(true)循環(huán),線(xiàn)程終止!
  }
}

說(shuō)明:在while(true)中不斷的執(zhí)行任務(wù),當(dāng)線(xiàn)程處于阻塞狀態(tài)時(shí),調(diào)用線(xiàn)程的interrupt()產(chǎn)生InterruptedException中斷。中斷的捕獲在while(true)之外,這樣就退出了while(true)循環(huán)!
注意:對(duì)InterruptedException的捕獲務(wù)一般放在while(true)循環(huán)體的外面,這樣,在產(chǎn)生異常時(shí)就退出了while(true)循環(huán)。否則,InterruptedException在while(true)循環(huán)體之內(nèi),就需要額外的添加退出處理。形式如下:

@Override
public void run() {
  while (true) {
    try {
      // 執(zhí)行任務(wù)...
    } catch (InterruptedException ie) { 
      // InterruptedException在while(true)循環(huán)體內(nèi)。
      // 當(dāng)線(xiàn)程產(chǎn)生了InterruptedException異常時(shí),while(true)仍能繼續(xù)運(yùn)行!需要手動(dòng)退出
      break;
    }
  }
}

說(shuō)明:上面的InterruptedException異常的捕獲在whle(true)之內(nèi)。當(dāng)產(chǎn)生InterruptedException異常時(shí),被catch處理之外,仍然在while(true)循環(huán)體內(nèi);要退出while(true)循環(huán)體,需要額外的執(zhí)行退出while(true)的操作。
2. 終止處于“運(yùn)行狀態(tài)”的線(xiàn)程
通常,我們通過(guò)“標(biāo)記”方式終止處于“運(yùn)行狀態(tài)”的線(xiàn)程。其中,包括“中斷標(biāo)記”和“額外添加標(biāo)記”。
(1) 通過(guò)“中斷標(biāo)記”終止線(xiàn)程。
形式如下:

@Override
public void run() {
  while (!isInterrupted()) {
    // 執(zhí)行任務(wù)...
  }
}

說(shuō)明:isInterrupted()是判斷線(xiàn)程的中斷標(biāo)記是不是為true。當(dāng)線(xiàn)程處于運(yùn)行狀態(tài),并且我們需要終止它時(shí);可以調(diào)用線(xiàn)程的interrupt()方法,使用線(xiàn)程的中斷標(biāo)記為true,即isInterrupted()會(huì)返回true。此時(shí),就會(huì)退出while循環(huán)。
注意:interrupt()并不會(huì)終止處于“運(yùn)行狀態(tài)”的線(xiàn)程!它會(huì)將線(xiàn)程的中斷標(biāo)記設(shè)為true。
(2) 通過(guò)“額外添加標(biāo)記”。
形式如下:

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

@Override
public void run() {
  while (flag) {
    // 執(zhí)行任務(wù)...
  }
}

說(shuō)明:線(xiàn)程中有一個(gè)flag標(biāo)記,它的默認(rèn)值是true;并且我們提供stopTask()來(lái)設(shè)置flag標(biāo)記。當(dāng)我們需要終止該線(xiàn)程時(shí),調(diào)用該線(xiàn)程的stopTask()方法就可以讓線(xiàn)程退出while循環(huán)。
注意:將flag定義為volatile類(lèi)型,是為了保證flag的可見(jiàn)性。即其它線(xiàn)程通過(guò)stopTask()修改了flag之后,本線(xiàn)程能看到修改后的flag的值。
綜合線(xiàn)程處于“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,比較通用的終止線(xiàn)程的形式如下:

@Override
public void run() {
  try {
    // 1. isInterrupted()保證,只要中斷標(biāo)記為true就終止線(xiàn)程。
    while (!isInterrupted()) {
      // 執(zhí)行任務(wù)...
    }
  } catch (InterruptedException ie) { 
    // 2. InterruptedException異常保證,當(dāng)InterruptedException異常產(chǎn)生時(shí),線(xiàn)程被終止。
  }
}

3. 終止線(xiàn)程的示例
interrupt()常常被用來(lái)終止“阻塞狀態(tài)”線(xiàn)程。參考下面示例:

// 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"); // 新建“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動(dòng)“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線(xiàn)程休眠300ms,然后主線(xiàn)程給t1發(fā)“中斷”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線(xiàn)程休眠300ms,然后查看t1的狀態(tài)。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運(yùn)行結(jié)果:

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.

結(jié)果說(shuō)明:
(1) 主線(xiàn)程main中通過(guò)new MyThread("t1")創(chuàng)建線(xiàn)程t1,之后通過(guò)t1.start()啟動(dòng)線(xiàn)程t1。
(2) t1啟動(dòng)之后,會(huì)不斷的檢查它的中斷標(biāo)記,如果中斷標(biāo)記為“false”;則休眠100ms。
(3) t1休眠之后,會(huì)切換到主線(xiàn)程main;主線(xiàn)程再次運(yùn)行時(shí),會(huì)執(zhí)行t1.interrupt()中斷線(xiàn)程t1。t1收到中斷指令之后,會(huì)將t1的中斷標(biāo)記設(shè)置“false”,而且會(huì)拋出InterruptedException異常。在t1的run()方法中,是在循環(huán)體while之外捕獲的異常;因此循環(huán)被終止。
我們對(duì)上面的結(jié)果進(jìn)行小小的修改,將run()方法中捕獲InterruptedException異常的代碼塊移到while循環(huán)體內(nèi)。

// 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"); // 新建“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動(dòng)“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線(xiàn)程休眠300ms,然后主線(xiàn)程給t1發(fā)“中斷”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線(xiàn)程休眠300ms,然后查看t1的狀態(tài)。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運(yùn)行結(jié)果:

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
...

結(jié)果說(shuō)明:
程序進(jìn)入了死循環(huán)!
為什么會(huì)這樣呢?這是因?yàn)椋瑃1在“等待(阻塞)狀態(tài)”時(shí),被interrupt()中斷;此時(shí),會(huì)清除中斷標(biāo)記[即isInterrupted()會(huì)返回false],而且會(huì)拋出InterruptedException異常[該異常在while循環(huán)體內(nèi)被捕獲]。因此,t1理所當(dāng)然的會(huì)進(jìn)入死循環(huán)了。
解決該問(wèn)題,需要我們?cè)诓东@異常時(shí),額外的進(jìn)行退出while循環(huán)的處理。例如,在MyThread的catch(InterruptedException)中添加break 或 return就能解決該問(wèn)題。
下面是通過(guò)“額外添加標(biāo)記”的方式終止“狀態(tài)狀態(tài)”的線(xiàn)程的示例:

// 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"); // 新建“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new."); 

      t1.start();           // 啟動(dòng)“線(xiàn)程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started."); 

      // 主線(xiàn)程休眠300ms,然后主線(xiàn)程給t1發(fā)“中斷”指令。
      Thread.sleep(300);
      t1.stopTask();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

      // 主線(xiàn)程休眠300ms,然后查看t1的狀態(tài)。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) { 
      e.printStackTrace();
    }
  } 
}

運(yùn)行結(jié)果:

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.

相關(guān)文章

  • SpringSecurity HttpSecurity 類(lèi)處理流程分析

    SpringSecurity HttpSecurity 類(lèi)處理流程分析

    SpringSecurity在SSM項(xiàng)目中使用基于配置文件,通過(guò)XML標(biāo)簽定義認(rèn)證信息,HttpSecurity在SpringBoot中通過(guò)代碼配置實(shí)現(xiàn)與XML相同功能,詳細(xì)介紹了HttpSecurity的類(lèi)結(jié)構(gòu)、處理過(guò)程及其與SecurityBuilder的關(guān)系,感興趣的朋友一起看看吧
    2024-09-09
  • 基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄

    基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄

    這篇文章主要為大家詳細(xì)介紹了基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Java并發(fā)編程中的CyclicBarrier線(xiàn)程屏障詳解

    Java并發(fā)編程中的CyclicBarrier線(xiàn)程屏障詳解

    這篇文章主要介紹了Java并發(fā)編程中的CyclicBarrier線(xiàn)程屏障詳解,
    2023-12-12
  • Spring Boot+Nginx實(shí)現(xiàn)大文件下載功能

    Spring Boot+Nginx實(shí)現(xiàn)大文件下載功能

    相信很多小伙伴,在日常開(kāi)放中都會(huì)遇到大文件下載的情況,大文件下載方式也有很多,比如非常流行的分片下載、斷點(diǎn)下載;當(dāng)然也可以結(jié)合Nginx來(lái)實(shí)現(xiàn)大文件下載,在中小項(xiàng)目非常適合使用,這篇文章主要介紹了Spring Boot結(jié)合Nginx實(shí)現(xiàn)大文件下載,需要的朋友可以參考下
    2024-05-05
  • Java?Zip壓縮之簡(jiǎn)化文件和文件夾的壓縮操作

    Java?Zip壓縮之簡(jiǎn)化文件和文件夾的壓縮操作

    這篇文章主要給大家介紹了關(guān)于Java?Zip壓縮之簡(jiǎn)化文件和文件夾的壓縮操作,Zip壓縮是一種常見(jiàn)的文件壓縮格式,它將多個(gè)文件和文件夾打包成一個(gè)以.zip為后綴的壓縮包,需要的朋友可以參考下
    2023-10-10
  • 一文帶你搞懂Redis分布式鎖

    一文帶你搞懂Redis分布式鎖

    本篇文章主要來(lái)介紹一下如何Redis實(shí)現(xiàn)分布式鎖的演進(jìn)過(guò)程,以及為什么不能直接用Setnx實(shí)現(xiàn)分布式鎖,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-09-09
  • SpringBoot線(xiàn)程池ThreadPoolTaskExecutor異步處理百萬(wàn)級(jí)數(shù)據(jù)

    SpringBoot線(xiàn)程池ThreadPoolTaskExecutor異步處理百萬(wàn)級(jí)數(shù)據(jù)

    本文主要介紹了SpringBoot線(xiàn)程池ThreadPoolTaskExecutor異步處理百萬(wàn)級(jí)數(shù)據(jù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • 在IDEA中創(chuàng)建SpringBoot項(xiàng)目的詳細(xì)步驟

    在IDEA中創(chuàng)建SpringBoot項(xiàng)目的詳細(xì)步驟

    這篇文章主要給大家介紹了在IDEA中創(chuàng)建SpringBoot項(xiàng)目的詳細(xì)步驟,文中有詳細(xì)的圖文介紹和代碼示例,對(duì)大家的學(xué)習(xí)和工作有一定的幫助,需要的朋友可以參考下
    2023-09-09
  • AQS(AbstractQueuedSynchronizer)抽象隊(duì)列同步器及工作原理解析

    AQS(AbstractQueuedSynchronizer)抽象隊(duì)列同步器及工作原理解析

    AQS是用來(lái)構(gòu)建鎖或者其他同步器組件的重量級(jí)基礎(chǔ)框架及整個(gè)JUC體系的基石,通過(guò)內(nèi)置的FIFO對(duì)列來(lái)完成資源獲取線(xiàn)程的排隊(duì)工作,并通過(guò)一個(gè)int類(lèi)型變量表示持有鎖的狀態(tài),本文給大家詳細(xì)介紹下AQS抽象隊(duì)列同步器的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2022-03-03
  • mybatis-plus指定字段模糊查詢(xún)的實(shí)現(xiàn)方法

    mybatis-plus指定字段模糊查詢(xún)的實(shí)現(xiàn)方法

    最近項(xiàng)目中使用springboot+mybatis-plus來(lái)實(shí)現(xiàn),所以下面這篇文章主要給大家介紹了關(guān)于mybatis-plus實(shí)現(xiàn)指定字段模糊查詢(xún)的相關(guān)資料,需要的朋友可以參考下
    2022-04-04

最新評(píng)論

广灵县| 光山县| 大渡口区| 石嘴山市| 恩平市| 剑河县| 兰考县| 随州市| 荔波县| 新建县| 耿马| 汉沽区| 德州市| 电白县| 行唐县| 恩平市| 曲麻莱县| 乐昌市| 安顺市| 蒙阴县| 巨野县| 电白县| 三台县| 古交市| 清水河县| 青海省| 靖边县| 基隆市| 贵德县| 仁布县| 托里县| 二手房| 桂东县| 长阳| 荔波县| 阿合奇县| 宣化县| 遂溪县| 胶南市| 正镶白旗| 旺苍县|