Java Thread Interrupt


線程,是編程中處理并發(fā)最常用的方式。但是如果用不好,也是一個比較麻煩的事情。畢竟創(chuàng)建一個線程是件容易的事情。但是怎么終止一個線程,卻不那么容易。關(guān)于線程的退出,最好的方式當然是讓線程處理完相應(yīng)的工作后自動退出。其次是主線程有效的通知到工作線程,“Hello, please exit!”。當然,暴力終止是不被推薦的,可能會發(fā)生數(shù)據(jù)一致性的問題?;蛘撸渌粗獑栴}。

我首先能想到的通知一個線程中斷,就是設(shè)置線程中斷標志。

import java.io.IOException;
import java.net.ServerSocket;

public class InterruptTest {

    private static boolean interrupt = false;
    
    public static boolean getInterrupt(){
        return interrupt;
    }
    
    public synchronized static void setInterupt(boolean value){
        interrupt = value;
    }
    
    public void method1(){
        try{
            int i=1;
            while(!interrupt){
                System.out.println("thread continue excute " + i++);
            }
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }
    
    public static void main(String args[]) throws InterruptedException, IOException{
        InterruptTest test = new InterruptTest();
        
        Thread thread = new Thread(new Runnable(){

            @Override
            public void run() {
                test.method1();
            }
            
        });
        
        thread.start();
        Thread.sleep(2000);
                InterruptTest.setInterupt(true);
        thread.join();
        
        System.out.println("Main thread finished!");
    }
}

這種方式當然可以有效的通知一直有任務(wù)運行的線程去中斷自己。但是,如果線程一直處于阻塞狀態(tài),比如Thread.sleep()。顯然線程是無法及時獲取中斷標志的??紤]下面這種場景。這個時候就該Thread.interrupt出場了。

import java.io.IOException;
import java.net.ServerSocket;

public class InterruptTest {

    private static boolean interrupt = false;
    public static boolean getInterrupt(){
        return interrupt;
    }
    
    public synchronized static void setInterupt(boolean value){
        interrupt = value;
    }
    
    public void method1(){
        try{
            int i=1;
            while(!interrupt){
                System.out.println("thread continue excute " + i++);
            }
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }
    
    public void method2(){
        try{
            int i=1;
            while(!interrupt){
                System.out.println("thread continue excute " + i++);
                Thread.sleep(3000);
                
            }
        }catch(Exception e){
            setInterupt(true);
            System.out.println(e.getMessage());
        }
    }
    
    public static void main(String args[]) throws InterruptedException, IOException{
        InterruptTest test = new InterruptTest();
        
        Thread thread = new Thread(new Runnable(){

            @Override
            public void run() {
                test.method2();
            }
            
        });
        
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
        thread.join();
        
        System.out.println("Main thread finished!");
    }
}

輸出結(jié)果為:

thread continue excute 1
sleep interrupted
Main thread finished!

Thread.sleep函數(shù)導致線程阻塞。interrput函數(shù)會發(fā)送一個java.lang.InterruptedException異常,當線程捕獲這個異常就會通知線程終止循環(huán)。
但調(diào)用interrupt函數(shù)也僅僅只能讓能接收InterruptedException異常的阻塞終止。其他一些I/O阻塞是不會理會interrupt函數(shù)發(fā)出的異常的。這種情況就需要針對不同的情況做處理了。比如,socket阻塞在accpet函數(shù)。interrupt函數(shù)就無能為力了。這時候就可以通過socket的close函數(shù)來關(guān)閉端口。

import java.io.IOException;
import java.net.ServerSocket;

public class InterruptTest {

    private static boolean interrupt = false;
    private ServerSocket socket1;
    
    public ServerSocket getSocket(){
        return socket1;
    }
    
    public static boolean getInterrupt(){
        return interrupt;
    }
    
    public synchronized static void setInterupt(boolean value){
        interrupt = value;
    }
    
    public void method1(){
        try{
            int i=1;
            while(!interrupt){
                System.out.println("thread continue excute " + i++);
            }
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }
    
    public void method2(){
        try{
            int i=1;
            while(!interrupt){
                System.out.println("thread continue excute " + i++);
                Thread.sleep(3000);
                
            }
        }catch(Exception e){
            setInterupt(true);
            e.printStackTrace();
        }
    }
    
    public void method3(){
        try{

            System.out.println("Start to run thread!");
            socket1 = new ServerSocket(8889);
            socket1.accept();
            System.out.println("Setup one connection!");
                
        }catch(Exception e){
            setInterupt(true);
            System.out.println(e.getMessage());
        }
    }
    
    public static void main(String args[]) throws InterruptedException, IOException{
        InterruptTest test = new InterruptTest();
        
        Thread thread = new Thread(new Runnable(){

            @Override
            public void run() {
                test.method3();
            }
            
        });
        
        thread.start();
        Thread.sleep(2000);
        test.getSocket().close();
        thread.join();
        
        System.out.println("Main thread finished!");
    }
}

輸出結(jié)果:

Start to run thread!
socket closed
Main thread finished!

其實在調(diào)用Socket.close函數(shù)的時候,socket線程會接收到一個java.net.SocketException異常。然后通過捕獲這個異常,改變線程中斷標志來中斷線程。

總之,如何有效的中斷一個線程。需要根據(jù)實際情況來處理。換到風險投資領(lǐng)域。進入之前就先想好退出方式。如果你的工作線程沒有阻塞,就用中斷標志控制就好。如果有一般阻塞,準備好處理interruptedException。如果有其他I/O阻塞,先提供阻塞對象的句柄獲取方式。然后準備好處理相應(yīng)的中斷異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、并發(fā) 進程:每個進程都擁有自己的一套變量 線程:線程之間共享數(shù)據(jù) 1.線程 Java中為多線程任務(wù)提供了很多的...
    SeanMa閱讀 2,805評論 0 11
  • 取消原因 取消一個任務(wù)執(zhí)行的理由有很多,通常有以下幾個 用戶請求取消通常用戶點擊“取消”按鈕發(fā)出取消命令 有時間限...
    德彪閱讀 2,145評論 0 2
  • 下面是我自己收集整理的Java線程相關(guān)的面試題,可以用它來好好準備面試。 參考文檔:-《Java核心技術(shù) 卷一》-...
    阿呆變Geek閱讀 15,127評論 14 507
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,597評論 1 15
  • 一、多線程 說明下線程的狀態(tài) java中的線程一共有 5 種狀態(tài)。 NEW:這種情況指的是,通過 New 關(guān)鍵字創(chuàng)...
    Java旅行者閱讀 4,860評論 0 44

友情鏈接更多精彩內(nèi)容