Java 多線程

2021-02-24 14:51 更新

Java線程教程 - Java多線程


以下代碼顯示了如何在程序中運(yùn)行多線程。

public class Main {
  public static void main(String[] args) {
    // Create two Thread objects
    Thread t1 = new Thread(Main::print);
    Thread t2 = new Thread(Main::print);

    // Start both threads
    t1.start();
    t2.start();
  }

  public static void print() {
    for (int i = 1; i <= 500; i++) {
      System.out.println(i);
    }
  }
}

上面的代碼生成以下結(jié)果。

線程同步

Java編程語(yǔ)言內(nèi)置了兩種線程同步:

  • 互斥同步
  • 條件同步

在互斥同步中,在一個(gè)時(shí)間點(diǎn)只允許一個(gè)線程訪問(wèn)代碼段。

條件同步通過(guò)條件變量和三個(gè)操作來(lái)實(shí)現(xiàn):等待,信號(hào)和廣播。


同步關(guān)鍵字

synchronized關(guān)鍵字用于聲明需要同步的關(guān)鍵部分。

有兩種方法可以使用synchronized關(guān)鍵字:

  • 將方法聲明為關(guān)鍵部分
  • 將語(yǔ)句塊聲明為關(guān)鍵段

我們可以通過(guò)在方法的返回類型之前使用關(guān)鍵字synchronized來(lái)聲明一個(gè)方法作為臨界段。

public class Main {
  public synchronized void someMethod_1() {
    // Method code goes here
  }

  public static synchronized void someMethod_2() {
    // Method code goes here
  }
}

我們可以聲明一個(gè)實(shí)例方法和一個(gè)靜態(tài)方法同步。構(gòu)造函數(shù)不能聲明為同步。

以下代碼說(shuō)明了使用關(guān)鍵字synchronized:

public class Main {
  public synchronized void someMethod_1() {
    // only one thread can execute here at a time
  }

  public void someMethod_11() {
    synchronized (this) {
      // only one thread can execute here at a time
    }
  }

  public void someMethod_12() {
    // multiple threads can execute here at a time
    synchronized (this) {
      // only one thread can execute here at a time
    }
    // multiple threads can execute here at a time
  }

  public static synchronized void someMethod_2() {
    // only one thread can execute here at a time
  }

  public static void someMethod_21() {
    synchronized (Main.class) {
      // only one thread can execute here at a time
    }
  }

  public static void someMethod_22() {
    // multiple threads can execute here at a time
    synchronized (Main.class) {
      // only one thread can execute here at a time
    }
    // multiple threads can execute here at a time
  }
}

wait()方法

對(duì)wait()方法的調(diào)用必須放在synchronized方法或同步塊中。

對(duì)于當(dāng)前線程已經(jīng)獲取監(jiān)視器的對(duì)象,必須調(diào)用wait()方法。

notify()方法

沒(méi)有辦法喚醒等待集中的特定線程。

例子

public class Main {
  private static int myValue = 1;

  public static void main(String[] args) {
    Thread t = new Thread(() -> {
      while (true) {
        updateBalance();
      }
    });
    t.start();
    t = new Thread(() -> {
      while (true) {
        monitorBalance();
      }
    });
    t.start();
  }

  public static synchronized void updateBalance() {
    System.out.println("start:" + myValue);
    myValue = myValue + 1;
    myValue = myValue - 1;
    System.out.println("end:" + myValue);
  }

  public static synchronized void monitorBalance() {
    int b = myValue;
    if (b != 1) {
      System.out.println("Balance  changed: " + b);
      System.exit(1); 
    }
  }
}

上面的代碼生成以下結(jié)果。

例2

以下代碼顯示了上述代碼的非同步版本。

public class Main {
  private static int myValue = 1;

  public static void main(String[] args) {
    Thread t = new Thread(() -> {
      while (true) {
        updateBalance();
      }
    });
    t.start();
    t = new Thread(() -> {
      while (true) {
        monitorBalance();
      }
    });
    t.start();
  }

  public static  void updateBalance() {
    System.out.println("start:" + myValue);
    myValue = myValue + 1;
    myValue = myValue - 1;
    System.out.println("end:" + myValue);
  }

  public static synchronized void monitorBalance() {
    int b = myValue;
    if (b != 1) {
      System.out.println("Balance  changed: " + b);
      System.exit(1); 
    }
  }
}

上面的代碼生成以下結(jié)果。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)