Javaの知識【並行ツール講座】

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();
        }
    }
}

おすすめ

転載: blog.csdn.net/m0_64550837/article/details/127327652