3. 同時実行ツール クラス
3.1 コンカレンシー ツール クラス - ハッシュテーブル
Hashtableが出現する理由: HashMap はコレクション クラスで一般的に使用されるコレクション オブジェクトですが、HashMap はスレッド アンセーフです (マルチスレッド環境では問題が発生する可能性があります)。データのセキュリティを確保するために Hashtable を使用できますが、Hashtable は非効率的です。
コード :
package com.itheima.mymap;
import java.util.HashMap;
import java.util.Hashtable;
public class MyHashtableDemo {
public static void main(String[] args) throws InterruptedException {
Hashtable<String, String> hm = new Hashtable<>();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
hm.put(i + "", i + "");
}
});
Thread t2 = new Thread(() -> {
for (int i = 25; i < 51; i++) {
hm.put(i + "", i + "");
}
});
t1.start();
t2.start();
System.out.println("----------------------------");
//为了t1和t2能把数据全部添加完毕
Thread.sleep(1000);
//0-0 1-1 ..... 50- 50
for (int i = 0; i < 51; i++) {
System.out.println(hm.get(i + ""));
}//0 1 2 3 .... 50
}
}
3.2 Concurrent ツール クラス - ConcurrentHashMap の基本的な使用法
ConcurrentHashMapが出現した理由: HashMap はコレクション クラスで一般的に使用されるコレクション オブジェクトですが、HashMap はスレッドセーフではありません (マルチスレッド環境では問題が発生する可能性があります)。データのセキュリティを確保するために Hashtable を使用できますが、Hashtable は非効率的です。
上記の2つの理由から、JDK1.5以降で提供されているConcurrentHashMapを利用できます。
建築 :
要約:
1, HashMap はスレッドセーフではありません。マルチスレッド環境ではデータ セキュリティの問題が発生します。
2, Hashtableはスレッドセーフですが、テーブル全体をロックしてしまうため効率が悪い
3. ConcurrentHashMap もスレッドセーフで効率的です。JDK7 と JDK8 では、基礎となる原則が異なります。
コード :
package com.itheima.mymap;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;
public class MyConcurrentHashMapDemo {
public static void main(String[] args) throws InterruptedException {
ConcurrentHashMap<String, String> hm = new ConcurrentHashMap<>(100);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
hm.put(i + "", i + "");
}
});
Thread t2 = new Thread(() -> {
for (int i = 25; i < 51; i++) {
hm.put(i + "", i + "");
}
});
t1.start();
t2.start();
System.out.println("----------------------------");
//为了t1和t2能把数据全部添加完毕
Thread.sleep(1000);
//0-0 1-1 ..... 50- 50
for (int i = 0; i < 51; i++) {
System.out.println(hm.get(i + ""));
}//0 1 2 3 .... 50
}
}
3.3 同時実行ツール クラス - ConcurrentHashMap 1.7 の原則
3.4 Concurrent ツール クラス - ConcurrentHashMap 1.8 の原則
要約:
1. ConcurrentHashMap オブジェクトが null パラメータ構成で作成された場合、何も実行されません。要素が初めて追加されたときにハッシュ テーブルを作成する
2. 現在の要素を格納するインデックスを計算します。
3. インデックス位置が null の場合は、cas アルゴリズムを使用して、このノードを配列に追加します。
4. インデックスの位置が null でない場合は、volatile キーワードを使用して、現在の位置で最新のノード アドレスを取得し、その下に吊るしてリンク リストにします。
5. 連結リストの長さが 8 以上の場合、自動的に赤黒木に変換されます 6. 連結リストまたは赤黒木の先頭ノードがロック オブジェクトとして使用され、悲観的ロックは、セットのマルチスレッド操作中のデータのセキュリティを確保するために使用されます
3.5 コンカレンシー ツール クラス - CountDownLatch
CountDownLatch クラス:
方法 | 説明 |
---|---|
public CountDownLatch(int カウント) | パラメータは、待機中のスレッドの数を示すスレッドの数を渡しました |
public void await() | スレッドを待機させる |
public void countDown() | 現在のスレッドの実行が終了しました |
使用シナリオ:実行する前に、他のスレッドの実行が終了するまでスレッドを待機させる
コード :
package com.itheima.mycountdownlatch;
import java.util.concurrent.CountDownLatch;
public class ChileThread1 extends Thread {
private CountDownLatch countDownLatch;
public ChileThread1(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
//1.吃饺子
for (int i = 1; i <= 10; i++) {
System.out.println(getName() + "在吃第" + i + "个饺子");
}
//2.吃完说一声
//每一次countDown方法的时候,就让计数器-1
countDownLatch.countDown();
}
}
package com.itheima.mycountdownlatch;
import java.util.concurrent.CountDownLatch;
public class ChileThread2 extends Thread {
private CountDownLatch countDownLatch;
public ChileThread2(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
//1.吃饺子
for (int i = 1; i <= 15; i++) {
System.out.println(getName() + "在吃第" + i + "个饺子");
}
//2.吃完说一声
//每一次countDown方法的时候,就让计数器-1
countDownLatch.countDown();
}
}
package com.itheima.mycountdownlatch;
import java.util.concurrent.CountDownLatch;
public class ChileThread3 extends Thread {
private CountDownLatch countDownLatch;
public ChileThread3(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
//1.吃饺子
for (int i = 1; i <= 20; i++) {
System.out.println(getName() + "在吃第" + i + "个饺子");
}
//2.吃完说一声
//每一次countDown方法的时候,就让计数器-1
countDownLatch.countDown();
}
}
package com.itheima.mycountdownlatch;
import java.util.concurrent.CountDownLatch;
public class MotherThread extends Thread {
private CountDownLatch countDownLatch;
public MotherThread(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
//1.等待
try {
//当计数器变成0的时候,会自动唤醒这里等待的线程。
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//2.收拾碗筷
System.out.println("妈妈在收拾碗筷");
}
}
package com.itheima.mycountdownlatch;
import java.util.concurrent.CountDownLatch;
public class MyCountDownLatchDemo {
public static void main(String[] args) {
//1.创建CountDownLatch的对象,需要传递给四个线程。
//在底层就定义了一个计数器,此时计数器的值就是3
CountDownLatch countDownLatch = new CountDownLatch(3);
//2.创建四个线程对象并开启他们。
MotherThread motherThread = new MotherThread(countDownLatch);
motherThread.start();
ChileThread1 t1 = new ChileThread1(countDownLatch);
t1.setName("小明");
ChileThread2 t2 = new ChileThread2(countDownLatch);
t2.setName("小红");
ChileThread3 t3 = new ChileThread3(countDownLatch);
t3.setName("小刚");
t1.start();
t2.start();
t3.start();
}
}
要約:
1. CountDownLatch(int count): パラメータは、待機中のスレッドの数を書き込みます。カウンターを定義します。
2. await(): スレッドを待機させます。カウンターが 0 の場合、待機中のスレッドを起動します。
3. countDown(): スレッドの実行が終了したときに呼び出され、カウンターは -1 になります。
3.6 同時実行ツール クラス - セマフォ
使用シーン:
特定のリソースにアクセスするスレッドの数を制御できます。
実装手順:
1. 誰かがこのチャンネルを管理する必要があります
2. 車が入ってきたらパスを発行
3.車が発車したら定期券を返却
4. 許可が出れば他の車両は待機のみ
コード :
package com.itheima.mysemaphore;
import java.util.concurrent.Semaphore;
public class MyRunnable implements Runnable {
//1.获得管理员对象,
private Semaphore semaphore = new Semaphore(2);
@Override
public void run() {
//2.获得通行证
try {
semaphore.acquire();
//3.开始行驶
System.out.println("获得了通行证开始行驶");
Thread.sleep(2000);
System.out.println("归还通行证");
//4.归还通行证
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.itheima.mysemaphore;
public class MySemaphoreDemo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
for (int i = 0; i < 100; i++) {
new Thread(mr).start();
}
}
}