国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

貓頭鷹的深夜翻譯:核心JAVA并發(fā)(二)

Pink / 842人閱讀

摘要:前言上一篇文章請參考貓頭鷹的深夜翻譯核心并發(fā)一安全發(fā)布發(fā)布一個對象是指該對象的引用對當前的域之外也可見比如,從方法中獲取一個引用。任務(wù)的功能性接口表示一個沒有返回值的任務(wù)表示一個包含返回值的計算。

前言

上一篇文章請參考貓頭鷹的深夜翻譯:核心JAVA并發(fā)(一)

安全發(fā)布

發(fā)布一個對象是指該對象的引用對當前的域之外也可見(比如,從getter方法中獲取一個引用)。要確保一個對象被安全的發(fā)布(即在初始化完成之后發(fā)布),可能需要使用同步。可以通過以下方法實現(xiàn)安全的發(fā)布:

靜態(tài)初始化方法。只有一個線程能夠初始化靜態(tài)變量因為該類的初始化是在一個排它鎖之下完成的。

class StaticInitializer {
  // Publishing an immutable object without additional initialization
  public static final Year year = Year.of(2017); 
  public static final Set keywords;
  // Using static initializer to construct a complex object
  static {
    // Creating mutable set
    Set keywordsSet = new HashSet<>(); 
    // Initializing state
    keywordsSet.add("java");
    keywordsSet.add("concurrency");
    // Making set unmodifiable 
    keywords = Collections.unmodifiableSet(keywordsSet); 
  }
}

volatile關(guān)鍵字。讀者線程總是能獲取最近的值,因為寫線程總是在后續(xù)的讀取之前進行

class Volatile {
  private volatile String state;
  void setState(String state) {
    this.state = state;
  }
  String getState() {
    return state; 
  }
}

Atomics。比如,AtomicInteger將一個值存儲為volatile類型,所以這里和volatile變量的規(guī)則相同

class Atomics {
  private final AtomicInteger state = new AtomicInteger();
  void initializeState(int state) {
    this.state.compareAndSet(0, state);
  }
  int getState() {
    return state.get();
  }
}

Final類型

class Final {
  private final String state;
  Final(String state) {
    this.state = state;
  }
  String getState() {
    return state;
  }
}
確保this引用不會再初始化過程中泄漏
class ThisEscapes {
 private final String name;
 ThisEscapes(String name) {
   Cache.putIntoCache(this);
   this.name = name;
 }
 String getName() { return name; }
}
class Cache {
 private static final Map CACHE = new ConcurrentHashMap<>();
 static void putIntoCache(ThisEscapes thisEscapes) {
   // "this" reference escaped before the object is fully constructed.
   CACHE.putIfAbsent(thisEscapes.getName(), thisEscapes);
 }
}

正確同步的域

class Synchronization {
  private String state;
  synchronized String getState() {
    if (state == null)
      state = "Initial";
    return state;
  }
}
不變的對象

不變對象的一個非常棒的屬性時,他們是現(xiàn)成安全的,所有無需在其上進行同步。是一個對象成為不變對象的要求為:

所有的字段為final類型

所有字段可以是可變對象或不可變對象,但不能越過對象的范圍,從而對象的狀態(tài)在構(gòu)建后不能更改。

this引用在初始化期間不會泄露

該類為final類型,所以無法在子類中修改其行為

不變對象的例子:

// Marked as final - subclassing is forbidden
public final class Artist {
  // Immutable object, field is final
  private final String name; 
  // Collection of immutable objects, field is final
  private final List tracks; 
  public Artist(String name, List tracks) {
    this.name = name;
    // Defensive copy
    List copy = new ArrayList<>(tracks); 
    // Making mutable collection unmodifiable
    this.tracks = Collections.unmodifiableList(copy); 
    // "this" is not passed to anywhere during construction
  }
  // Getters, equals, hashCode, toString
}
// Marked as final - subclassing is forbidden
public final class Track { 
  // Immutable object, field is final
  private final String title; 
  public Track(String title) {
    this.title = title;
  }
  // Getters, equals, hashCode, toString
}
Threads

java.lang.Thread類用來表示一個應(yīng)用或是一個JVM現(xiàn)場。其代碼通常在某個進程類的上下文中執(zhí)行。(使用Thread#currentThread來獲取當前線程本身)

線程的狀態(tài)和相應(yīng)的描述:

NEW: 還未啟動
RUNNABLE: 啟動并運行
BLOCKED: 在控制器上等待 - 該線程正視圖獲取鎖并進入關(guān)鍵區(qū)域
WAITING: 等待另一個線程執(zhí)行特殊操作(notify/notifyAll,LockSupport#unpark)
TIMED_WAITING: 和WAITING類似,但是有超時設(shè)置
TERMINATED: 停止

Thread的方法和相應(yīng)的描述:

start: 啟動一個Thread實例并且執(zhí)行run()方法
join: 阻塞直到線程完成
interrupt: 中斷線程。如果該線程在響應(yīng)終端的方法中阻塞著,則會在另一個線程中拋出InterruptedException,否則將會被設(shè)置為中斷狀態(tài)。
stop,suspend,resume,destroy: 這些方法都已經(jīng)失效了。
如何處理InterruptedException

如果可能的話,清理資源并終止線程的運行

聲明當前的方法會拋出InterruptedException

如果一個方法并沒有被聲明拋出InterruptedException,應(yīng)該使用Thread.currentThread().interrupt()將中斷標識回復(fù)為true,然后在該層拋出異常。將中斷標識設(shè)為true很重要,它使得異常在可以在更高的層次上進行處。

意料之外的異常處理

Threads可以設(shè)置UncaughtExceptionHandler,它會在程序突然中斷的時候收到通知。

Thread thread = new Thread(runnable);
thread.setUncaughtExceptionHandler((failedThread, exception) -> {
  logger.error("Caught unexpected exception in thread "{}".",
      failedThread.getName(), exception);
});
thread.start();
生命力 死鎖

當多個線程在等待彼此釋放持有的資源,從而形成了資源占有和等待的循環(huán)時,就產(chǎn)生了死鎖。可能產(chǎn)生死鎖的例子:

class Account {
  private long amount;
  void plus(long amount) { this.amount += amount; }
  void minus(long amount) {
    if (this.amount < amount)
      throw new IllegalArgumentException();
    else
      this.amount -= amount;
  }
  static void transferWithDeadlock(long amount, Account first, Account second){
    synchronized (first) {
      synchronized (second) {
        first.minus(amount);
        second.plus(amount);
      }
    }
  }
}

死鎖可能會這樣產(chǎn)生:

一個線程正視圖從第一個賬戶向第二個賬戶轉(zhuǎn)賬,并且已經(jīng)獲得了第一個賬戶的鎖

與此同時,另一個線程正視圖從第二個線程像第一個線程轉(zhuǎn)賬,并且已經(jīng)獲得了第二個賬戶的鎖

避免死鎖的方法有:

順序加鎖 - 總是按相同的順序獲得鎖

class Account {
  private long id;
  private long amount;
  // Some methods are omitted
  static void transferWithLockOrdering(long amount, Account first, Account second){
    boolean lockOnFirstAccountFirst = first.id < second.id;
    Account firstLock = lockOnFirstAccountFirst  ? first  : second;
    Account secondLock = lockOnFirstAccountFirst ? second : first;
    synchronized (firstLock) {
      synchronized (secondLock) {
        first.minus(amount);
        second.plus(amount);
      }
    }
  }
}

會超時的鎖 - 不要無限的占有鎖,應(yīng)當釋放所有的鎖并重新嘗試獲取

class Account {
  private long amount;
  // Some methods are omitted
  static void transferWithTimeout(
      long amount, Account first, Account second, int retries, long timeoutMillis
  ) throws InterruptedException {
    for (int attempt = 0; attempt < retries; attempt++) {
      if (first.lock.tryLock(timeoutMillis, TimeUnit.MILLISECONDS))
      {
        try {
          if (second.lock.tryLock(timeoutMillis, TimeUnit.MILLISECONDS))
          {
            try {
              first.minus(amount);
              second.plus(amount);
            }
            finally {
              second.lock.unlock();
            }
          }
        }
        finally {
          first.lock.unlock();
        }
      }
    }
  }
}
活鎖和線程饑餓

當所有的線程都在協(xié)商對資源的訪問,或是預(yù)防死鎖,從而導(dǎo)致沒有一個線程真正在運行時,會產(chǎn)生活鎖。當一個線程長時間占據(jù)一個鎖導(dǎo)致別的線程無法進展時,會產(chǎn)生線程饑餓現(xiàn)象。

java.util.concurrent 線程池

線程池的核心接口是ExecutorServicejava.util.concurrent還提供了一個靜態(tài)工廠Executors,它包含創(chuàng)建具有最常見配置的線程池的工廠方法。

工廠方法如下:

newSingleThreadExecutor: 返回一個只有一個線程的ExecutorService
newFixedThreadPool: 返回一個具有固定數(shù)目線程的ExecutorService
newCachedThreadPool: 返回一個可變大小的線程池ExecutorService
newSingleThreadScheduledExecutor: 返回只有一個線程的ScheduledExecutorService
newScheduledThreadPool: 返回包含一組線程的ScheduledExecutorService
newWorkStealingPool: 返回一個帶有并行級別的ExecutorService
當調(diào)整線程池大小時,最好基于機器運行該應(yīng)用時分配的邏輯內(nèi)核數(shù)。可以通過調(diào)用Runtime.getRuntime().availableProcessors()來獲得該值。

線程池的實現(xiàn)類

任務(wù)通過ExecutorService#submitExecutorService#invokeAllExecutorService#invokeAny提交,它們對不同類型的任務(wù)有多種重載。

任務(wù)的功能性接口:

Runnable: 表示一個沒有返回值的任務(wù)
Callable: 表示一個包含返回值的計算。它還聲明可以拋出原始異常,所以不需要對檢查異常進行包裝
Future

Future是對所有的異步計算的抽象。它表示這些計算的結(jié)果,在某些時候可用。大多數(shù)的ExecutorService方法都是用Future作為返回值。它包含檢查當前future的狀態(tài)以及阻塞當前讀取操作直至結(jié)果可以被讀取等方法。

ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(() -> "result");
try {
  String result = future.get(1L, TimeUnit.SECONDS);
  System.out.println("Result is "" + result + "".");
} 
catch (InterruptedException e) {
  Thread.currentThread().interrupt();
  throw new RuntimeException(e);
} 
catch (ExecutionException e) {
  throw new RuntimeException(e.getCause());
} 
catch (TimeoutException e) {
  throw new RuntimeException(e);
}
assert future.isDone();
Locks

Lock
java.util.concurrent.locks包中有一個標準的Lock接口,ReentrantLock實現(xiàn)復(fù)制了synchronized關(guān)鍵字的功能,同時提供了一些額外的功能,比如獲取當前鎖狀態(tài)的信息,非阻塞的tryBlock()方法,以及可中斷的鎖。下面是使用具體的ReentrantLock實例的例子:

class Counter {
  private final Lock lock = new ReentrantLock();
  private int value;
  int increment() {
    lock.lock();
    try {
      return ++value;
    } finally {
      lock.unlock();
    }
  }
}

ReadWriteLock
java.util.concurrent.locks包還包含了ReadWriteLock接口(以及ReentrantReadWriteLock實現(xiàn)),它被定義為一組讀寫鎖,支持多個同步讀者和單一寫者。

class Statistic {
  private final ReadWriteLock lock = new ReentrantReadWriteLock();
  private int value;
  void increment() {
    lock.writeLock().lock();
    try {
      value++;
    } finally {
      lock.writeLock().unlock();
    }
  }
  int current() {
    lock.readLock().lock();
    try {
      return value;
    } finally {
      lock.readLock().unlock();
    }
  }
}

CountDownLatch
CountDownLatch通過一個數(shù)值初始化。線程會調(diào)用await()方法阻塞自己,等待計數(shù)值為0后再繼續(xù)運行。其它的線程(或是同一個線程)調(diào)用countDown()來減少計數(shù)。一旦計數(shù)為0后,該倒計時器便不可以重復(fù)使用。用來在達到某個條件后,啟動一組未知數(shù)量的線程

CompletableFuture
CompletableFuture是異步計算的一個抽象。不同于Future,只能通過阻塞獲取結(jié)果,該類鼓勵注冊回調(diào)函數(shù)來創(chuàng)建一組任務(wù),從而在得到返回值或是出現(xiàn)異常時執(zhí)行該任務(wù)。


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號!將會不定期的發(fā)放福利哦~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70993.html

相關(guān)文章

  • 頭鷹深夜翻譯核心JAVA并發(fā)(一)

    摘要:簡介從創(chuàng)建以來,就支持核心的并發(fā)概念如線程和鎖。這篇文章會幫助從事多線程編程的開發(fā)人員理解核心的并發(fā)概念以及如何使用它們。請求操作系統(tǒng)互斥,并讓操作系統(tǒng)調(diào)度程序處理線程停放和喚醒。 簡介 從創(chuàng)建以來,JAVA就支持核心的并發(fā)概念如線程和鎖。這篇文章會幫助從事多線程編程的JAVA開發(fā)人員理解核心的并發(fā)概念以及如何使用它們。 (博主將在其中加上自己的理解以及自己想出的例子作為補充) 概念 ...

    Richard_Gao 評論0 收藏0
  • 頭鷹深夜翻譯:Volatile原子性, 可見性和有序性

    摘要:有可能一個線程中的動作相對于另一個線程出現(xiàn)亂序。當實際輸出取決于線程交錯的結(jié)果時,這種情況被稱為競爭條件。這里的問題在于代碼塊不是原子性的,而且實例的變化對別的線程不可見。這種不能同時在多個線程上執(zhí)行的部分被稱為關(guān)鍵部分。 為什么要額外寫一篇文章來研究volatile呢?是因為這可能是并發(fā)中最令人困惑以及最被誤解的結(jié)構(gòu)。我看過不少解釋volatile的博客,但是大多數(shù)要么不完整,要么難...

    Lionad-Morotar 評論0 收藏0
  • 頭鷹深夜翻譯:為何需要緩存以及如何實現(xiàn)緩存

    摘要:由于需要跨進程訪問網(wǎng)絡(luò)上的高速緩存,因此延遲,故障和對象序列化會導(dǎo)致性能下降。應(yīng)用程序高速緩存會自動清除條目以保持其內(nèi)存占用。緩存統(tǒng)計高速緩存統(tǒng)計信息可幫助識別高速緩存的運行狀況并提供有關(guān)高速緩存行為和性能的信息。 前言 這篇文章探索了現(xiàn)有的各種JAVA緩存基數(shù),它們對各種場景下提高應(yīng)用的性能起著重要的作用。 近十年來,信息技術(shù)極高的提升了業(yè)務(wù)流程,它已經(jīng)成為了全球企業(yè)的戰(zhàn)略性方案。它...

    FuisonDesign 評論0 收藏0
  • 頭鷹深夜翻譯:JDK Vs. JRE Vs. JVM之間區(qū)別

    摘要:什么是為執(zhí)行字節(jié)碼提供一個運行環(huán)境。它的實現(xiàn)主要包含三個部分,描述實現(xiàn)規(guī)格的文檔,具體實現(xiàn)和滿足要求的計算機程序以及實例具體執(zhí)行字節(jié)碼。該類先被轉(zhuǎn)化為一組字節(jié)碼并放入文件中。字節(jié)碼校驗器通過字節(jié)碼校驗器檢查格式并找出非法代碼。 什么是Java Development Kit (JDK)? JDK通常用來開發(fā)Java應(yīng)用和插件。基本上可以認為是一個軟件開發(fā)環(huán)境。JDK包含Java Run...

    blair 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<