1. 程式人生 > >Java高併發--停止執行緒和中斷執行緒

Java高併發--停止執行緒和中斷執行緒

一、停止執行緒

在java中如果想要停止一個執行緒,我們可以使用stop()方法,但是建議最好不要只用這個方法,因為這個方法會破壞資料的一致性。那麼為什麼會發生這種情況呢?因為在我們呼叫Thread.stop()方法的時候,會釋放掉執行緒持有的鎖,而這個鎖就是保持執行緒一致性的關鍵。

下面我們將使用一個例子來展示呼叫Thread.stop()帶來的後果。

/**
 * 終止執行緒
 *
 * @author LIUTAO
 * @version 2017/9/23
 * @see
 */
public class StopTest {
    public static User user = new User();
    public static class User{
        private int id;
        private String name;

        public User(){
            id = 0;
            name = "0";
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

    /**
     * 改變執行緒
     */
    public static class ChangeThread extends Thread{
        @Override
        public void run(){
            while(true){
                synchronized (user){
                    int v = (int)(System.currentTimeMillis()/1000);
                    user.setId(v);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    user.setName(String.valueOf(v));
                }
                Thread.yield();
            }
        }
    }

    /**
     * 讀取執行緒
     */
    public static class ReadThread extends Thread{
        @Override
        public void run(){
            while(true){
                synchronized (user){
                    if(user.getId() != Integer.valueOf(user.getName())){
                        System.out.println(user);
                    }
                }
                Thread.yield();
            }
        }
    }

    public static void main(String[] args) {
        new ReadThread().start();
        while (true){
            Thread thread = new ChangeThread();
            thread.start();
            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            thread.stop();
        }
    }
}
通過執行上面的程式碼我們可以看見下面的執行結果:
User{id=1506153677, name='1506153676'}
User{id=1506153677, name='1506153676'}
可以看見這並不是我們想要的結果(使用者的id和name相同),這就是我們在使用stop()方法破壞掉了資料一致性。

那麼我們到底該如何終止一個執行緒呢?請看如下的程式碼

/**
     * 改變執行緒
     */
    public static class ChangeThread extends Thread{
        private boolean stop = false;

        public void stopMe(){
            stop = true;
        }
        @Override
        public void run(){
            while(true){
                synchronized (user){
                    int v = (int)(System.currentTimeMillis()/1000);
                    user.setId(v);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    user.setName(String.valueOf(v));
                }
                Thread.yield();
            }
        }
    }
我們在ChangeThread執行緒中加入了stop屬性,並且提供了方法來設定這個屬性,當執行緒判斷到這個屬性為true的時候就停止掉執行緒有關資料一致性的操作就行。

二、中斷執行緒

針對上面的執行緒停止,我們可以看見,如果我們線上程執行的過程張突然停止掉一個執行緒會造成執行緒裡面的資料不一致的問題,那麼java多執行緒有沒有提供更好的方法來終止一個執行緒,而不會造成資料不一致的問題?當然,這就是我們要說到的中斷執行緒。

中斷執行緒只是告訴目標執行緒你需要退出了,而至於目標執行緒是否退出,完全由目標執行緒自行決定。

java API針對中斷執行緒提供了三個方法,分別是Thread.interrupt()、Thread.isInterrupted()、Thread.interrupted()。這三個方法分別用於通知執行緒中斷、判斷執行緒是中斷、判斷執行緒是否中斷並且清除執行緒中斷的狀態。

public class InterruptTest {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run(){
                while(!Thread.currentThread().isInterrupted()){
                    System.out.println("current thread is alive!");
                    break;
                }
                Thread.yield();
                System.out.println("current thread is dead!");
            }
        };

        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread.interrupt();
    }
}
程式執行結果:
current thread is alive!
current thread is dead!
從上面的執行結果我們可以看出,最終執行緒是自己獲取到中斷通知進行的一個退出執行緒的操作。

但是我們要注意到一個點,如果我們在一個執行緒睡眠的過程中,對執行緒呼叫了中斷操作,這個時候執行緒就會丟擲異常,這個異常就會清理掉中斷標誌,所以我們在異常捕獲的時候需要再次為當前執行緒加上中斷標誌。




相關推薦

Java併發--停止執行中斷執行

一、停止執行緒 在java中如果想要停止一個執行緒,我們可以使用stop()方法,但是建議最好不要只用這個方法,因為這個方法會破壞資料的一致性。那麼為什麼會發生這種情況呢?因為在我們呼叫Thread.stop()方法的時候,會釋放掉執行緒持有的鎖,而這個鎖就是保持執行緒一致

Java併發(六)——ThreadLocal為執行保駕護航

       前邊我們講述多執行緒互動,多執行緒引起的安全問題,多執行緒安全的問題解決同步(synchronized、lock、CAS)……這一切的一切起源就是共享資源,共享臨界區的資料安全引起的。那我們從另外一個角度想想呢?每個執行緒有自

Java 併發程式設計詳解:多執行與架構設計

內容簡介 本書主要包含四個部分: 部分主要闡述 Thread 的基礎知識,詳細介紹執行緒的 API 使用、執行緒安全、執行緒間資料通訊,以及如何保護共享資源等內容,它是深入學習多執行緒內容的基礎。 第二部分引入了 ClassLoader,這是因為 ClassLoader 與執行緒不無關係

Java併發程式設計》學習 --3.2 執行複用:執行

1)什麼是執行緒池 為了避免系統頻繁地建立和銷燬執行緒,我們可以讓建立的執行緒進行復用。執行緒池中,總有那麼幾個活躍執行緒。當你需要使用執行緒時,可以從池子中隨便拿一個空閒執行緒,當完成工作時,並不急著關閉執行緒,而是將整個執行緒退回到池子,方便其他人使用。 2)JDK對執

關於java併發的一些感悟經驗已經我自己找的資料

我們通過一個連結地址訪問,通過這個連結地址,伺服器對應的模組處理這個請求,轉到對應的jsp頁面,最後生成我們要的資料。但是,如果上千萬個請求的話,有太多的高併發請求,那麼就會加重伺服器的壓力,最壞的情況是把伺服器down掉。那麼如何避免這種情況的出現呢?如果我們把最初對test.do的請求結果儲存成一個ht

Java併發程式設計:取消關閉

Java沒有提供任何機制來安全地終止執行緒,但是它提供了中斷(Interruption).這是一種協作機制,能夠使一個執行緒終止另一個執行緒當前的工作。 在對一個執行緒物件呼叫Thread.interrupted()方法之後,一般情況下對這個執行緒不會產生任何影響。因為

java執行併發庫應用(二)執行建立定時任務Timer

1、建立執行緒的兩種方式, 通過start, 執行run方法。 第一種實現runnable, 定義類實現Runnable介面 重寫Runnable介面中的run方法 通過Thread建立執行緒物件 將Runnable介面的子類物件作為實際引數傳遞

JAVA併發(二)------區分執行程序

執行緒與程序 程序是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎,在早期面向程序設計的計算機結構中,程序是程式的基本執行實體,在當代面向執行緒的計算機結構中,程序是執行緒的容器,程式是指令資料及其組織形式的描述,程序

Java併發程式設計學習筆記(三):Java記憶體模型執行安全

文章目錄 原子性 有序性 可見性 – 編譯器優化 – 硬體優化(如寫吸收,批操作) Java虛擬機器層面的可見性 Happen-Before規則(先行發生) 程式順序原則: volat

Java併發--等待執行結束謙讓

針對本格專題我們主要討論join()和yield()這兩個方法。 一、等待執行緒結束 如果我們想要在一個執行緒中獲取到另外一個執行緒的處理結果,那麼 這個時候我們該怎麼辦呢?最好的方式當然就是等待另一個執行緒的結束後再來執行當前執行緒,這個時候就該我們的join()方法上場

實戰Java併發程式設計之Java記憶體模型執行安全

Java記憶體模型 原子性: 是指一個操作是不可中斷的.即使多個執行緒一起執行的時候,一個操作一旦開始,就不會被其他執行緒干擾. 一般CPU的指令是原子的. Q:i++是原子操作嗎? A:不是.

JAVA併發執行必須懂的50個問題

ImportNew  首頁所有文章資訊Web架構基礎技術書籍教程Java小組工具資源  Java執行緒面試題 Top 50  2014/08/21 | 分類: 基礎技術 | 27 條評論 | 標籤: 多執行緒, 面試題  分享到: 692  本文由

實戰Java併發程式設計(3.2 執行池)

1.Executor jdk提供了一套Executor框架,本質上是一個執行緒池。 newFixedThreadPool()方法:該方法返回一個固定數量的執行緒池。該執行緒池中的執行緒數量始終不變,當有一個新任務提交時,執行緒池中若有空閒執行緒,則立即執行,若沒有,則任務會暫存在一個任

Java併發程式設計——多執行

執行緒簡介 程序 正在執行的程式。 程序是系統進行資源分配和呼叫的獨立單位。每一個程序都有他自己的記憶體空間和系統資源。 執行緒 在同一個程序內又可以執行多個任務。而這每一個任務就可以看成是一個執行緒。

Java併發——多執行協作,同步控制

      繼上一篇:Java高併發——多執行緒基礎 中講到,共享資源的合理使用,才能夠使多執行緒程式有條不紊的執行。其中我們通過synchronized來實現臨界區資源的是否可以訪問。而,這篇我們來重點總結synchronized的增強替代版鎖,以及其它JD

Java併發——多執行基礎

       在上一篇 JAVA高併發——瞭解並行世界 中我們回顧了一些多執行緒的概念知識。這裡先舉個例子,來看現實生活中的多執行緒例子:一個家庭中有爸爸、媽媽、兒子,家中有電視、洗衣機、書桌等,如果媽媽領著兒子出去了,爸爸就可以

java併發學習(九)-----多執行的團隊協作:同步控制

Java高併發學習(八)-------多執行緒的團隊協作:同步控制   同步控制是併發程式必不可少的重要手段。之前介紹的synchronized關鍵字就是一種最簡單的控制方法。同時,wait()和notify()方法起到了執行緒等待和通知的作用。這些工具對於實現複雜的多

Java併發程式設計之第一階段,多執行基礎深入淺出

汪文君高併發程式設計第一階段01講-課程大綱及主要內容介紹 汪文君高併發程式設計第一階段02講-簡單介紹什麼是執行緒 汪文君高併發程式設計第一階段03講-建立並啟動執行緒 汪文君高併發程式設計第一階段04講-執行緒生命週期以及start方法原始碼剖析 汪文君高併發程式設計第

Java併發程式設計:執行

這裡首先介紹了java5中的併發的小工具包:java.util.concurrent.atomic,然後介紹了執行緒池的概念,對使用java5的方式建立不同形式的執行緒進行了演示,之後介紹了兩個 物件:Callable和Future,用於獲取執行緒執行後的結果,

Java併發程式設計(十一):Java執行

在開發過程中,合理地使用執行緒池能夠帶來3個好處。 降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。 提高執行緒的可管理性。執行緒是稀缺資源,如果無限制地建立