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