iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
0
Software Development

30 天介紹 Java 的 Thread系列 第 26

Day 26 介紹 Single Threaded Execution 模式

  • 分享至 

  • xImage
  •  

今天要介紹 Single Threaded Execution 模式,其實從它的字面翻譯就可以知道它是一個單執行緒執行模式,在什麼情境之下會使用到此模式?主要是有多個執行緒要存取同一個共享變數時會使用到此模式,就像是在 Day 7 時有介紹到為何要使用 Synchronized 來保護共享變數。因為我們無法去預期有可能不同的執行緒同時存取相同的變數,造成程式出錯。

以下使用執行緒不安全的方式,寫一個 Sample Code:

public class Data {
  private String value1 = "";
  private String value2 = "";

  public void setValue(String value1, String value2) {
    this.value1 = value1;
    this.value2 = value2;
    System.out.println(this.value1 + "  " + this.value2 + "  " + isValueEquals());
  }

  private boolean isValueEquals() {
    return this.value1.equals(this.value2);
  }
}

以上的 Data 類別主要是一個可以給多個執行緒使用的 class,它的功能就是在不同的執行緒會設定不同的值,目的是用來測試執行緒安不安全

public class ThreadExample implements Runnable {
  private Data data;
  private String value1;
  private String value2;

  public ThreadExample(Data data, String value1, String value2) {
    this.data = data;
    this.value1 = value1;
    this.value2 = value2;
  }

  @Override
  public void run() {
    try {
      while (true) {
        Thread.sleep(500L);
        this.data.setValue(this.value1, this.value2);
      }
    } catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
}

執行緒程式裡面主要會把主程式設定的值傳入,設定給 Data 的共享變數裡面,以下是主程式 Sample Code:

public class Test1 {
  public static void main(String args[]) {
    Data data = new Data();

    for (int i = 1 ; i <= 1000 ; i++) {
      Thread thread = new Thread(new ThreadExample(data, "value" + i, "value" + i));
      thread.start();
    }
  }
}

在主程式裡面會使用迴圈開 100 個執行緒來執行,ThreadExample 的執行緒建構子會傳入相同的值,用來確認共享變數會不會被其它的執行緒干擾,執行的結果如下:

value308  value308  true
value353  value353  true
value283  value283  true
value349  value349  true
value305  value305  false
value337  value337  true
value335  value335  true
value363  value363  true
value309  value309  true
value375  value375  true

從執行的結果來看 Data 類別是執行緒不安全的程式,因為雖然印出 value305 的值都是相同的,但卻印出 false 所以在執行的過程中有被其它的執行緒干擾,才會印出 false。要修改此問題需要修改 Data 這個類別,程式如下:

public class Data {
  private String value1 = "";
  private String value2 = "";

  public synchronized void setValue(String value1, String value2) {
    this.value1 = value1;
    this.value2 = value2;
    System.out.println(this.value1 + "  " + this.value2 + "  " + isValueEquals());
  }

  private boolean isValueEquals() {
    return this.value1.equals(this.value2);
  }
}

在 setValue 的方法前面加上 Synchronized 的關鍵字就可以解決這個問題,但這會影響到多執行緒執行的效能因為要另外的去等待其它執行執行完才會進入執行。如果在意執行效能的話需要把 Data 類別修改成前幾天介紹的 Immutable 模式,也是另外一個解決共享變數互斥的方法。


上一篇
Day 25 介紹 Balking 模式
下一篇
Day 27 介紹 Guarded Suspension 模式
系列文
30 天介紹 Java 的 Thread30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言