java并发与锁

120 阅读2分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

并发工具类

public class MyHashMapDemo {
    public static void main(String[] args) throws InterruptedException {
        HashMap<String, String> hm = new HashMap<>();
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 25; i++) {
                hm.put(i+"",i+"");
            } 
        });

        Thread t2 = new Thread(()->{
            for (int i = 25; i < 50; i++) {
                hm.put(i+"",i+"");
            }
        });

        t1.start();
        t2.start();

        System.out.println("-------------------");
        // 为了t1和t2能把数据全部添加完毕
        Thread.sleep(1000);

        for (int i = 0; i < 51; i++) {
            System.out.println(hm.get(i+""));
        }
    }
}

打印结果会出现 null null 47 48 49

Hashtable HashMap 是线程不安全的(多线程环境下可能会存在问题)。 为了保证数据的安全性,我们可以使用Hashtable,但是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 < 50; i++) {
                hm.put(i+"",i+"");
            }
        });

        t1.start();
        t2.start();

        System.out.println("-------------------");
        // 为了t1和t2能把数据全部添加完毕
        Thread.sleep(1000);

        for (int i = 0; i < 51; i++) {
            System.out.println(hm.get(i+""));
        }
    }
}

截屏2021-11-08 下午5.05.42.png

截屏2021-11-08 下午5.06.21.png

ConcurrentHashMap:

截屏2021-11-08 下午5.07.22.png


public class MyConcurrentHashMapDemo {
    public static void main(String[] args) throws InterruptedException {
        ConcurrentHashMap<String, String> hm = new ConcurrentHashMap<>();
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 25; i++) {
                hm.put(i+"",i+"");
            } 
        });

        Thread t2 = new Thread(()->{
            for (int i = 25; i < 50; i++) {
                hm.put(i+"",i+"");
            }
        });

        t1.start();
        t2.start();

        System.out.println("-------------------");
        // 为了t1和t2能把数据全部添加完毕
        Thread.sleep(1000);

        for (int i = 0; i < 51; i++) {
            System.out.println(hm.get(i+""));
        }
    }
}

小结:

截屏2021-11-08 下午5.09.32.png

ConcurrentHashMap1.7版本原理解析:

截屏2021-11-08 下午5.10.41.png

截屏2021-11-08 下午5.11.30.png

截屏2021-11-08 下午5.12.08.png

截屏2021-11-08 下午5.12.29.png

截屏2021-11-08 下午5.13.00.png

截屏2021-11-08 下午5.13.20.png

截屏2021-11-08 下午5.13.49.png

截屏2021-11-08 下午5.14.27.png

截屏2021-11-08 下午5.14.51.png

截屏2021-11-08 下午5.15.13.png

jdk 1.7时, 在默认情况下,最多允许16个线程同时访问。

截屏2021-11-08 下午5.16.20.png

截屏2021-11-08 下午5.17.46.png

截屏2021-11-08 下午5.18.27.png

截屏2021-11-08 下午5.18.49.png

截屏2021-11-08 下午5.20.58.png

截屏2021-11-08 下午5.21.26.png

CountDownLatch

截屏2021-11-08 下午5.22.47.png

截屏2021-11-08 下午5.23.20.png

截屏2021-11-08 下午5.23.37.png

public class ChildThread extends Thread{

    private CountDownLatch countDownLatch;

    public ChildThread(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        // 1. 吃饺子
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + "在吃第" + i+ "个饺子");
        }
        // 2. 吃完说一声
        // 每一次countdown方法的时候,就让计数器-1
        countDownLatch.countDown();
    }
}
public class ChildThread2 extends Thread{

    private CountDownLatch countDownLatch;

    public ChildThread2(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        // 1. 吃饺子
        for (int i = 0; i < 15; i++) {
            System.out.println(getName() + "在吃第" + i+ "个饺子");
        }
        // 2. 吃完说一声
        // 每一次countdown方法的时候,就让计数器-1

        countDownLatch.countDown();
    }
}
public class ChildThread3 extends Thread{
    private CountDownLatch countDownLatch;

    public ChildThread3(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        // 1. 吃饺子
        for (int i = 0; i < 20; i++) {
            System.out.println(getName() + "在吃第" + i+ "个饺子");
        }
        // 2. 吃完说一声
        // 每一次countdown方法的时候,就让计数器-1
        countDownLatch.countDown();
    }
}
public class MontherThread extends Thread{

    private CountDownLatch countDownLatch;

    public MontherThread(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        // 1.等待
        try {
            // 当计数器编程0的时候,会自动唤醒这里等待的线程
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 2. 收拾碗筷
        System.out.println("妈妈收拾碗筷");
    }
}

public class MyCountDownLatchDemo {
    public static void main(String[] args) {
        // 1.创建CountDownLatch的对象,需要传递给四个线程
        // 在底层就定义了一个计数器,此时计数器的值就是3
        CountDownLatch countDownLatch = new CountDownLatch(3);
        // 2.创建四个线程对象并开启他们。
        MontherThread montherThread = new MontherThread(countDownLatch);
        montherThread.start();

        ChildThread t1 = new ChildThread(countDownLatch);
        t1.setName("小明");

        ChildThread2 t2 = new ChildThread2(countDownLatch);
        t2.setName("小黑");

        ChildThread3 t3 = new ChildThread3(countDownLatch);
        t3.setName("小白");

        t1.start();
        t2.start();
        t3.start();
    }
}

截屏2021-11-08 下午5.37.27.png

Semaphore

截屏2021-11-08 下午5.37.55.png

截屏2021-11-08 下午5.38.34.png

截屏2021-11-08 下午5.38.48.png

截屏2021-11-08 下午5.39.11.png

截屏2021-11-08 下午5.39.31.png

public class MyRunnable implements Runnable {
    // 1. 获取管理员对象
    private Semaphore semaphore = new Semaphore(2);
    @Override
    public void run() {
        // 2.获得通行证
        try {
            semaphore.acquire();
            System.out.println("拿到通行证开始行驶");
            Thread.sleep(2000);
            System.out.println("归还通行证");
            // 3. 开始行驶
            // 4. 归还通行证
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

public class MySemaphoreDemo {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        for (int i = 0; i < 100; i++) {
            new Thread(mr).start();
        }
    }
}