java写一个阻塞队列 ,顺序打印线程abc,DCL 双重检查加锁

写一个DCL 双重检查加锁(double-checked locking)

1,使用 volatile 防止指令重排序,(jmm加载顺序)
2,第一次判断当前对象是否为空
3,如果为空加synchronized
4.再检查一遍对象等于空 创建对象,因为此时如果有2个线程都在sync等待,如果不检查1线程创建后2线程还会进入再创建一次,这样就不是单例了。

package com.lisongtao.juc.a_juc;

import java.util.Arrays;

public class Singleton {

    private static volatile Singleton singleton = new Singleton();
    private Singleton() {
        System.out.println("进入");
    }
    private static Singleton getSingleton(){
        if(singleton==null){
            synchronized (Singleton.class){
                if(singleton==null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    public static void main(String[] args) {
        Thread[] ths = new Thread[2000];
        for(int i=0; i<ths.length; i++) {
            ths[i] = new Thread(()->{
                System.out.println(Singleton.getSingleton());
            });
        }

        Arrays.asList(ths).forEach(o->o.start());
    }
    } 
}

java写一个阻塞队列

1,先创建 ReentrantLock
2, 通过ReentrantLock实例出 Condition
3,实例化 Queue 用于存储

ReentrantLock ?

Condition ?

什么是 await()/ signal() 和wait() / nofity()?区别?

await()/ signal() 和 锁定机制Lock直接挂钩 。通过在Lock对象上调用newCondition()方法,将条件变量和一个锁对象进行绑定,进而控制并发程序访问竞争资源的安全。

package com.lisongtao.juc.a_juc;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ProviderConsumer<T> {
    ReentrantLock lock = new ReentrantLock();
    Condition pCondition = lock.newCondition();
    Condition cConditon = lock.newCondition();
    private int length;
    private Queue<T> queue;


    public ProviderConsumer(int length) {
        this.length = length;
        this.queue = new LinkedList<T>();
    }

    public void provide(T product) {
        lock.lock();
        try {
            while (queue.size() >= length) {
                pCondition.await();
            }
            queue.add(product);
            cConditon.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();

        }
    }

    public T consume() {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                cConditon.await();
            }
            T product = queue.remove();
            pCondition.signal();
            return product;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }

    public static void main(String[] args) {
        ProviderConsumer p = new ProviderConsumer(3);

        Thread[] thread = new Thread[10];
        Thread[] thread2 = new Thread[5];

        for (int i=0; i<thread.length;i++){
            int finalI = i;
            thread[i] = new Thread(() -> {
                p.provide(finalI);
            });
        }
        for (int i=0; i<thread2.length;i++){
            thread2[i] = new Thread(() -> {
                Object consume = p.consume();
                System.out.println(consume.toString());
            });
        }
        Arrays.asList(thread).forEach(o->o.start());
        Arrays.asList(thread2).forEach(o->o.start());

    }

}


顺序打印线程abc

1,先创建三个 线程类 分别打印ABC 实现 Runnable接口
2,定义一个count值用于计算打印顺序, count% 3 得到的取余值按照大小 调用 conditionB.signal(); 如果与对应的值不相等,进入等待,直到相等的出现再进行打印。

package com.lisongtao.juc.a_juc;


import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class PrintABC {
    //    volatile int value = 0;
    private AtomicInteger value = new AtomicInteger(0);
    /**
     * 使用可重入锁
     */
    ReentrantLock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();
    //打印多少遍
    private int count;

    public PrintABC(int count) {
        this.count = count;
    }

    private void PrintABC() {
        new Thread(new ThreadA()).start();
        new Thread(new ThreadB()).start();
        new Thread(new ThreadC()).start();
    }

    /**
     * 创建三个线程类
     * ThreadA ThreadB ThreadC
     */
    class ThreadA implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < count; i++) {
                    if (value.get() % 3 != 0) {
                        conditionA.await();
                    }
                    System.out.print("A");
                    conditionB.signal();
                    value.getAndIncrement();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    class ThreadB implements Runnable {
        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < count; i++) {

                    if (value.get() % 3 != 1) {
                        conditionB.await();
                    }
                    System.out.print("B");
                    conditionC.signal();
                    value.getAndIncrement();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    class ThreadC implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < count; i++) {
                    if (value.get() % 3 != 2) {
                        conditionC.await();
                    }
                    System.out.println("C");
                    conditionA.signal();
                    value.getAndIncrement();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        PrintABC printABC = new PrintABC(5);
        printABC.PrintABC();
    }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值