ArrayList,linkedlistとConcurrentLinkedQueueの違いについて詳しく述べる
4198 ワード
ArrayList
ArrayListは、動的配列に相当する配列キューです.Javaの配列に比べて容量が動的に増加します.AbstractListに継承され、List、RandomAccess、Cloneable、java.io.Serializableなどのインタフェースを実現します.ArrayListはAbstractListを継承し,Listを実現した.これは配列キューであり、関連する追加、削除、変更、遍歴などの機能を提供します.ArrayListはRandmoAccessインタフェースを実現し,ランダムアクセス機能を提供する.RandmoAccessはjavaでListによって実装され、Listに高速アクセス機能を提供するために使用される.ArrayListでは、要素のシーケンス番号で要素オブジェクトをすばやく取得できます.これが高速ランダムアクセスです.後で、Listの「高速ランダムアクセス」と「Iterator反復器によるアクセス」の効率を比較します.ArrayListはCloneableインタフェースを実現し,すなわち関数clone()を上書きし,クローン化できる.ArrayListはjava.io.Serializableインタフェースを実現し、これはArrayListがシーケンス化をサポートし、シーケンス化によって伝送できることを意味する.Vectorと異なり、ArrayListでの動作はスレッドセキュリティではありません.したがって、単一スレッドでArrayListを使用することを推奨し、マルチスレッドではVectorまたはCopyOnWriteArrayListを選択することができる
LinkedList
JavaではLinkedListはスレッドが安全ではありませんが、マルチスレッドプログラムで複数のスレッドがLinkedListにアクセスしている場合はどのような問題が発生しますか?
C o n c u r r e ntModificationExceptionの放出
JDKコードでは,ListItrのadd(),next(),previous(),remove(),set()メソッドがConcurrentModificationExceptionから飛び出す.
コードではmodCountはLinkedList構造が変更された回数を記録する.Iterator初期化の場合、expectedModCount=modCountとなります.LinkedList構造をIteratorで変更する動作は、expectedModCountとmodCountを同時に更新し、両方の値を等しくします.LinkedListオブジェクトでその構造を変更する方法でmodCountのみが更新されます.したがって,2つのスレッドAとBがあると仮定する.AはLinkedListをIteratorによって遍歴して修正し、Bは同時にオブジェクトによってその構造を修正すると、Iteratorに関する方法は異常を放出する.これは、スレッド競合によるエラーが比較的容易に発見されます.
LinkedListオブジェクトによる構造の変更
両方のスレッドがLinkedListオブジェクトで構造を変更している場合、どうなりますか?まずJDKにおけるLinkedListのデータ構造を見てみましょう. 作者:scholfield 出典:CSDN 原文:https://blog.csdn.net/scholfield/article/details/4739093 本文は博主のオリジナルの文章で、転載して博文のリンクを添付してください!
ConcurrentLinkedQueue
public class Test01ConcurrentLinkedQueue { public static void main(String[] args) throws InterruptedException { int peopleNum=10000;//食事人数 int tablenum=10;//食卓数
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); CountDownLatch count=new CountDownLatch(tableNum);カウンタ//
//食事人数を列に入れる(食事をする人が並ぶ) for(int i=1;i<=peopleNum;i++){ Queue.offer(「消費者_」+i); } //10個のスレッドを実行してキューから要素を取り出します(10個のテーブルから食事を開始します) System.out.println(「------------------------------------------------------------------------------------------------------------------------------」); long start = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(tableNum); for(int i=0;i executorService.submit(new Dinner("00"+ (i+1), queue, count)); } //カウンタ待ち、キューが空であることを知っています(全員が食べ終わった) count.await(); long time = System.currentTimeMillis() - start; System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- System.out.println(「共消費時間:」+time); //スレッドプールの停止 executorService.shutdown(); }
private static class Dinner implements Runnable{ private String name; private ConcurrentLinkedQueue queue; private CountDownLatch count;
public Dinner(String name, ConcurrentLinkedQueue queue, CountDownLatch count) { this.name = name; this.queue = queue; this.count = count; }
@Override public void run() { //while (queue.size() > 0){ while (!queue.isEmpty()){ //キューから要素を取り出して並んでいる人は1人足りません System.out.println(""+queue.poll()+"----完食...、食卓番号:"+name); } count.countDown();//カウンタ-1 } } }
ArrayListは、動的配列に相当する配列キューです.Javaの配列に比べて容量が動的に増加します.AbstractListに継承され、List、RandomAccess、Cloneable、java.io.Serializableなどのインタフェースを実現します.ArrayListはAbstractListを継承し,Listを実現した.これは配列キューであり、関連する追加、削除、変更、遍歴などの機能を提供します.ArrayListはRandmoAccessインタフェースを実現し,ランダムアクセス機能を提供する.RandmoAccessはjavaでListによって実装され、Listに高速アクセス機能を提供するために使用される.ArrayListでは、要素のシーケンス番号で要素オブジェクトをすばやく取得できます.これが高速ランダムアクセスです.後で、Listの「高速ランダムアクセス」と「Iterator反復器によるアクセス」の効率を比較します.ArrayListはCloneableインタフェースを実現し,すなわち関数clone()を上書きし,クローン化できる.ArrayListはjava.io.Serializableインタフェースを実現し、これはArrayListがシーケンス化をサポートし、シーケンス化によって伝送できることを意味する.Vectorと異なり、ArrayListでの動作はスレッドセキュリティではありません.したがって、単一スレッドでArrayListを使用することを推奨し、マルチスレッドではVectorまたはCopyOnWriteArrayListを選択することができる
LinkedList
JavaではLinkedListはスレッドが安全ではありませんが、マルチスレッドプログラムで複数のスレッドがLinkedListにアクセスしている場合はどのような問題が発生しますか?
C o n c u r r e ntModificationExceptionの放出
JDKコードでは,ListItrのadd(),next(),previous(),remove(),set()メソッドがConcurrentModificationExceptionから飛び出す.
コードではmodCountはLinkedList構造が変更された回数を記録する.Iterator初期化の場合、expectedModCount=modCountとなります.LinkedList構造をIteratorで変更する動作は、expectedModCountとmodCountを同時に更新し、両方の値を等しくします.LinkedListオブジェクトでその構造を変更する方法でmodCountのみが更新されます.したがって,2つのスレッドAとBがあると仮定する.AはLinkedListをIteratorによって遍歴して修正し、Bは同時にオブジェクトによってその構造を修正すると、Iteratorに関する方法は異常を放出する.これは、スレッド競合によるエラーが比較的容易に発見されます.
LinkedListオブジェクトによる構造の変更
両方のスレッドがLinkedListオブジェクトで構造を変更している場合、どうなりますか?まずJDKにおけるLinkedListのデータ構造を見てみましょう. 作者:scholfield 出典:CSDN 原文:https://blog.csdn.net/scholfield/article/details/4739093 本文は博主のオリジナルの文章で、転載して博文のリンクを添付してください!
ConcurrentLinkedQueue
。 FIFO( ) 。 。 。
, 。 collection ,ConcurrentLinkedQueue 。 null 。
public class Test01ConcurrentLinkedQueue { public static void main(String[] args) throws InterruptedException { int peopleNum=10000;//食事人数 int tablenum=10;//食卓数
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); CountDownLatch count=new CountDownLatch(tableNum);カウンタ//
//食事人数を列に入れる(食事をする人が並ぶ) for(int i=1;i<=peopleNum;i++){ Queue.offer(「消費者_」+i); } //10個のスレッドを実行してキューから要素を取り出します(10個のテーブルから食事を開始します) System.out.println(「------------------------------------------------------------------------------------------------------------------------------」); long start = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(tableNum); for(int i=0;i executorService.submit(new Dinner("00"+ (i+1), queue, count)); } //カウンタ待ち、キューが空であることを知っています(全員が食べ終わった) count.await(); long time = System.currentTimeMillis() - start; System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- System.out.println(「共消費時間:」+time); //スレッドプールの停止 executorService.shutdown(); }
private static class Dinner implements Runnable{ private String name; private ConcurrentLinkedQueue queue; private CountDownLatch count;
public Dinner(String name, ConcurrentLinkedQueue queue, CountDownLatch count) { this.name = name; this.queue = queue; this.count = count; }
@Override public void run() { //while (queue.size() > 0){ while (!queue.isEmpty()){ //キューから要素を取り出して並んでいる人は1人足りません System.out.println(""+queue.poll()+"----完食...、食卓番号:"+name); } count.countDown();//カウンタ-1 } } }