溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java項目中的多線程有哪些關(guān)鍵字

發(fā)布時間:2020-11-18 15:19:25 來源:億速云 閱讀:233 作者:Leah 欄目:編程語言

Java項目中的多線程有哪些關(guān)鍵字?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一、同步(synchronized)和異步(asynchronized)

1、同步(synchronized)簡單說可以理解為共享的意思,如果資源不是共享的,就沒必要進行同步。設(shè)置共享資源為同步的話,可以避免一些臟讀情況。

2、異步(asynchronized)簡單說可以理解為獨立不受到其他任何制約。

舉個例子:

線程1調(diào)用了帶有synchronized關(guān)鍵字的方法methodA,線程2調(diào)用了異步方法methodB,出現(xiàn)的現(xiàn)象是同時控制臺輸出 t1,t2。

package com.ietree.multithread.sync;

/**
 * 多線程之對象同步鎖和異步鎖Demo
 *
 * @author ietree
 */
public class SynAndAsynDemo {

  public static void main(String[] args) {
    
    final SynAndAsynDemo mo = new SynAndAsynDemo();
    
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodA();
      }
    },"t1");
    
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodB();
      }
    },"t2");
    
    t1.start();
    t2.start();
  }
  
  // 方法A
  public synchronized void methodA(){
    try {
      System.out.println(Thread.currentThread().getName());
      // 休眠4秒
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  
  // 方法B
  public void methodB(){
    System.out.println(Thread.currentThread().getName());
  }
  
}

線程1調(diào)用了帶有synchronized關(guān)鍵字的方法methodA,線程2調(diào)用了帶有synchronized關(guān)鍵字的方法methodB,出現(xiàn)的現(xiàn)象是首先輸出t1,等待4秒之后再輸出t2。

package com.ietree.multithread.sync;

/**
 * 多線程之對象同步鎖和異步鎖Demo
 *
 * @author ietree
 */
public class SynAndAsynDemo {

  public static void main(String[] args) {
    
    final SynAndAsynDemo mo = new SynAndAsynDemo();
    
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodA();
      }
    },"t1");
    
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        mo.methodB();
      }
    },"t2");
    
    t1.start();
    t2.start();
  }
  
  // 方法A
  public synchronized void methodA(){
    try {
      System.out.println(Thread.currentThread().getName());
      // 休眠4秒
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  
  // 方法B
  public synchronized void methodB(){
    System.out.println(Thread.currentThread().getName());
  }
  
}

結(jié)論:

在第一段代碼中t1線程先持有object對象的Lock鎖,t2線程可以以異步的方式調(diào)用對象中的非synchronized修飾的方法,所以同時輸出;

在第二段代碼中t1線程先持有object對象的Lock鎖,t2線程如果在這個時候調(diào)用對象中的同步(synchronized)方法則需等待,也就是同步。

二、volatile

作用:volatile關(guān)鍵字的作用是:使變量在多個線程間可見(具有可見性),但是僅靠volatile是不能保證線程的安全性,volatile關(guān)鍵字不具備synchronized關(guān)鍵字的原子性。

Demo1:

package com.ietree.multithread.sync;

public class RunThread extends Thread {
  // volatile
  private boolean isRunning = true;

  private void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }

  public void run() {
    System.out.println("進入run方法..");
    int i = 0;
    while (isRunning == true) {
      // ..
    }
    System.out.println("線程停止");
  }

  public static void main(String[] args) throws InterruptedException {
    RunThread rt = new RunThread();
    rt.start();
    Thread.sleep(1000);
    rt.setRunning(false);
    System.out.println("isRunning的值已經(jīng)被設(shè)置了false");
  }
}

程序輸出:

進入run方法..
isRunning的值已經(jīng)被設(shè)置了false

之后進入死循環(huán)

Demo2:

package com.ietree.multithread.sync;

public class RunThread extends Thread {
  // volatile
  private volatile boolean isRunning = true;

  private void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }

  public void run() {
    System.out.println("進入run方法..");
    int i = 0;
    while (isRunning == true) {
      // ..
    }
    System.out.println("線程停止");
  }

  public static void main(String[] args) throws InterruptedException {
    RunThread rt = new RunThread();
    rt.start();
    Thread.sleep(1000);
    rt.setRunning(false);
    System.out.println("isRunning的值已經(jīng)被設(shè)置了false");
  }
}

程序輸出:

isRunning的值已經(jīng)被設(shè)置了false
線程停止

總結(jié):當多個線程之間需要根據(jù)某個條件確定 哪個線程可以執(zhí)行時,要確保這個條件在 線程之間是可見的。因此,可以用volatile修飾。

volatile 與 synchronized 的比較:

①volatile輕量級,只能修飾變量。synchronized重量級,還可修飾方法

②volatile只能保證數(shù)據(jù)的可見性,不能用來同步,因為多個線程并發(fā)訪問volatile修飾的變量不會阻塞。

synchronized不僅保證可見性,而且還保證原子性,因為,只有獲得了鎖的線程才能進入臨界區(qū),從而保證臨界區(qū)中的所有語句都全部執(zhí)行。多個線程爭搶synchronized鎖對象時,會出現(xiàn)阻塞。

線程安全性包括兩個方面,①可見性。②原子性。

從上面自增的例子中可以看出:僅僅使用volatile并不能保證線程安全性。而synchronized則可實現(xiàn)線程的安全性。

關(guān)于Java項目中的多線程有哪些關(guān)鍵字問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI