主要就是获得锁lock()的地方应用了CAS
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/*
* 手写一个自旋锁(底层是CAS)
*/
public class SpinlockDemo {
// 原子引用,解决JMM中原子性问题,底层是unsafe类,其下面的各个方法是CAS在java中的体现
AtomicReference<Thread> reference = new AtomicReference<Thread>();
public void lock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "\t 来了! ");
do {
// 循环
} while (!reference.compareAndSet(null, thread));
}
private void unlock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "\t 释放了锁! ");
reference.compareAndSet(thread, null);
}
public static void main(String[] args) {
SpinlockDemo spinlockDemo = new SpinlockDemo();
new Thread(() -> {
spinlockDemo.lock();
// System.out.println(Thread.currentThread().getName() + "\t 来了! ");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinlockDemo.unlock();
// System.out.println(Thread.currentThread().getName() + "\t 释放了锁!
// ");
}, "first").start();
new Thread(() -> {
spinlockDemo.lock();//如果first不释放锁,这个second就一直在这里自旋
System.out.println(Thread.currentThread().getName() + "\t 终于轮到我了! ");
spinlockDemo.unlock();
// System.out.println(Thread.currentThread().getName() + "\t 释放了锁!
// ");
}, "second").start();
}
}
输出:
first 来了!
second 来了!
first 释放了锁!
second 终于轮到我了!
second 释放了锁!
/*
* 单例模式,DCL版+volatile禁止重排
*/
public class Singleton {
// 这个地方是懒汉式,如果下面没有if判断,就是饿汉式,防止面试问到
// 这里加volatile是为了防止指令重排
private static volatile Singleton instance = null;
// 精髓之处,将constructor私有化
private Singleton() {
System.out.println("dddd");
}
public static Singleton getInstance() {
if (instance == null) {
// 这里的synchronized是DCL双重锁检测,
// 就像去房间,先敲门,进去了再按按门,看有没有锁严实,再做事
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
//test
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->Singleton.getInstance(),String.valueOf(i)).start();;
}
}
}
import java.util.concurrent.TimeUnit;
/*
* 测试volatile保证可见性
*/
public class Seeable {
// 外部类可以通过实例访问内部类的私有变量
static class MyData {
private int num = 0;
// private volatile int num = 0; 此处加上volatile保证可见性
public void changeData() {
this.num = 10;
}
}
public static void main(String[] args) {
MyData myData = new MyData();
// 乃木达表达式,期间用TimeUnit让线程休眠3秒
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " come in");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 改变数据
myData.changeData();
System.out.println("num = " + myData.num);
}, "Ding").start();
// 如果num没有用colatile修,那么mian和Ding线程之间是不可见的,对于main来说,num一直为0,就会一直在这里循环,出不去
while (myData.num == 0) {
}
// 如果num加了volatile修饰,就会执行到这里,并打印这句话
System.out.println(Thread.currentThread().getName() + " mission complete");
}
}
import java.util.concurrent.atomic.AtomicInteger;
/*
* 测试volatile不保证原子性
*/
class MyData {
volatile int num = 1;
public void addNum() {
num++;
}
// 因为colatile不保证原子性,这里用JUC里面的AtomicInteger类,构造函数里面的值是初始化value,默认为0
AtomicInteger atomicInteger = new AtomicInteger(1);
public void atomicAddNum() {
atomicInteger.getAndAdd(1); // 相当于i++,参数是每次加多少
}
}
public class AtonicTest {
public static void main(String[] args) {
MyData myData = new MyData();
for (int i = 0; i < 20; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
// myData.addNum();
// 这里用AtomicInteger类的方法,保证原子性
myData.atomicAddNum();
}
}, String.valueOf(i)).start();
}
// 如果后台线程大于2(后台默认有一个main和GC线程),就让线程继续执行
while (Thread.activeCount() > 2) {
Thread.yield();
}
System.out.println("最终的num值是: " + myData.atomicInteger);
}
}
/*
* 测试syn可重入锁
*/
public class SynDemo {
static class Phone {
public synchronized void getName() {
System.out.println(Thread.currentThread().getName() + " getName");
getId();
}
public synchronized void getId() {
System.out.println(Thread.currentThread().getName() + " getId");
}
}
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(() -> phone.getName(), "first").start();
new Thread(() -> phone.getName(), "second").start();
}
}
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
/*
* 测试ReentrantLock可重入锁
*/
public class ReentrantDemo {
public static ReentrantLock lock = new ReentrantLock();
public static void getName() {
lock.lock();
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " getName()");
getId();
} finally {
lock.unlock();
}
}
public static void getId() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " getId()");
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
new Thread(() -> getName(), "first").start();
new Thread(() -> getName(), "second").start();
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
/*
* ArrayList线程不安全示范:add方法没有加syn
*/
public class ContainerNotSafeDemo {
public static void main(String[] args) {
//1、用vector:List list = new Vector();
//2、用集合类Collections:List list = Collections.synchronizedList(new ArrayList());
List<Integer> list = new CopyOnWriteArrayList<Integer>();
// 会引发并发修改异常:java.util.ConcurrentModificationException
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(3);
System.out.println(list);
}).start();
}
}
}
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*
* 读写锁
*/
class Source {
volatile HashMap<String, Object> map = new HashMap<String, Object>();
//可重复写入的读写锁,只要是在写,其他线程都不能读或写
ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
public void set(String str, Object obj) {
try {
rwlock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "-正在写入:" + str);
map.put(str, obj);
System.out.println(Thread.currentThread().getName() + "-写入完成");
} finally {
rwlock.writeLock().unlock();
}
}
public void get(String str) {
try {
rwlock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "-正在读取");
Object object = map.get(str);
System.out.println(Thread.currentThread().getName() + "-读取完成" + object);
} finally {
rwlock.writeLock().unlock();
}
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
Source source = new Source();
for (int i = 0; i < 5; i++) {
final int temp = i;
new Thread(() -> {
source.set(temp + "", temp + "");
}, String.valueOf(i)).start();
}
// 睡眠2秒,保证写操作全部完成
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
final int temp = i;
new Thread(() -> {
source.get(temp + "");
}, String.valueOf(i)).start();
}
}
}
输出:
1-正在写入:1
1-写入完成
0-正在写入:0
0-写入完成
2-正在写入:2
2-写入完成
3-正在写入:3
3-写入完成
4-正在写入:4
4-写入完成
0-正在读取
0-读取完成0
2-正在读取
2-读取完成2
1-正在读取
1-读取完成1
4-正在读取
4-读取完成4
3-正在读取
3-读取完成3
首先创建一个枚举类:
/*
* CountDownLatch的枚举类
*/
public enum StudentEnum {
one(1, "赵"), two(2, "钱"), three(3, "孙"), fore(4, "李"), five(5, "周"), six(6, "吴");
private Integer num;
private String name;
public Integer getNum() {
return num;
}
public String getName() {
return name;
}
private StudentEnum(Integer num, String name) {
this.num = num;
this.name = name;
}
public static StudentEnum forEach(int index) {
StudentEnum[] enums = StudentEnum.values();
for (StudentEnum studentEnum : enums) {
if (studentEnum.getNum() == index) {
return studentEnum;
}
}
return null;
}
}
再来测试类:
import java.util.concurrent.CountDownLatch;
/*
* CountDownLatch测试
*/
public class CountDownLatchDemo {
static CountDownLatch countDownLatch = new CountDownLatch(6);
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= 6 ; i++) {
final int tem = i;
new Thread(()->{
System.out.println(StudentEnum.forEach(tem).getName() + "同学走了");
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + ":############班长锁门");
}
}
输出:
赵同学走了
孙同学走了
钱同学走了
周同学走了
吴同学走了
李同学走了
main:############班长锁门(不使用CountDownLatch的话,班长就不会在最后锁门了)
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/*
* CyclicBarrierDemo
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("神龙,出来吧!");
});
for (int i = 1; i <= 7; i++) {
final int temp = i;
new Thread(() -> {
System.out.println("收集到第" + temp + "个龙珠");
//这里加一个await()方法,就可以在七颗龙珠还没有收集完之前都在等待
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
输出:
收集到第1个龙珠
收集到第2个龙珠
收集到第3个龙珠
收集到第5个龙珠
收集到第6个龙珠
收集到第7个龙珠
收集到第4个龙珠
神龙,出来吧!
}
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/*
* SemaphoreDemo
*/
public class SemaphoreDemo {
public static void main(String[] args) {
// 海底捞空3个座位
Semaphore semaphore = new Semaphore(3);
// 有6个人在等待
for (int i = 1; i <= 7; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "获得座位");
TimeUnit.SECONDS.sleep(3);// 吃饭三秒
System.out.println(Thread.currentThread().getName() + "吃完走人");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
输出:
1获得座位
2获得座位
3获得座位
3吃完走人
1吃完走人
2吃完走人
5获得座位
7获得座位
4获得座位
5吃完走人
7吃完走人
6获得座位
4吃完走人
6吃完走人
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/*
* SynchronousQueue测试
*/
public class SynchronousQueueDemo {
// SynchronousQueue不存储数据,只能每次put一个,等到take了之后才能继续take
public static void main(String[] args) {
SynchronousQueue<Integer> synqueue = new SynchronousQueue<Integer>();
new Thread(() -> {
try {
// 加入
System.out.println(Thread.currentThread().getName() + " put 1");
synqueue.put(1);
System.out.println(Thread.currentThread().getName() + " put 2");
synqueue.put(2);
System.out.println(Thread.currentThread().getName() + " put 3");
synqueue.put(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "first").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "拿到了:" + synqueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "拿到了:" + synqueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "拿到了:" + synqueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
输出:
first put 1
Thread-0拿到了:1
first put 2
Thread-0拿到了:2
first put 3
Thread-0拿到了:3
要求如下:
AA打印5次,BB打印10次,CC打印15次
循环10轮
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/*
* 题目:顺序打印A-B-C
* AA打印5次,BB打印10次,CC打印15次,然后循环10轮
*/
class Ding {
private int flagNum = 1;
private ReentrantLock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
private void print(int num) {
for (int i = 1; i <= num; i++) {
System.out.println(Thread.currentThread().getName() + "\t " + i);
}
}
public void print5() {
lock.lock(); // 加锁
try {
while (flagNum != 1) { // 如果flag不是1,等待
c1.await();
}
print(5); // 打印5次
flagNum = 2; // 将flag变为2
c2.signal(); // 唤醒c2
} catch (Exception e) {
} finally {
lock.unlock(); // 释放锁
}
}
public void print10() {
lock.lock();
try {
while (flagNum != 2) {
c2.await();
}
print(10);
flagNum = 3;
c3.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void print15() {
lock.lock();
try {
while (flagNum != 3) {
c3.await();
}
print(15);
flagNum = 1;
c1.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
public class LockConditionDemo {
public static void main(String[] args) {
Ding ding = new Ding();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
ding.print5();
}, "AA").start();
new Thread(() -> {
ding.print10();
}, "BB").start();
new Thread(() -> {
ding.print15();
}, "CC").start();
}
}
}
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/*
* 自测:A生产一个B消费一个
*/
class PrintOneByOneResource {
private volatile Integer num = 1;
ReentrantLock lock = new ReentrantLock();
private Condition cpro = lock.newCondition();
private Condition ccon= lock.newCondition();
public void product() {
lock.lock();
try {
while (num != 1) {
cpro.await();
}
System.out.println(Thread.currentThread().getName() + "生产了一个");
num = 2;
ccon.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void consume() {
lock.lock();
try {
while (num != 2) {
ccon.await();
}
System.out.println(Thread.currentThread().getName() + "消费了一个");
num = 1;
cpro.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
public class PrintOneByOne {
public static void main(String[] args) {
PrintOneByOneResource source = new PrintOneByOneResource();
for (int i = 0; i < 20; i++) {
new Thread(() -> {
source.product();
}, "A").start();
new Thread(() -> {
source.consume();
}, "B").start();
}
}
}
要求:生产一个消费一个,然后可以停止(不用syn,不用锁,用阻塞队列和原子引用)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/*
* 生产者消费者模式-阻塞队列版
* 要求:生产一个消费一个,然后可以停止
*
*/
class ProdConsResource {
private volatile boolean flag = true; // 生产消费的flag
private AtomicInteger atomicInteger = new AtomicInteger(); // 原子引用,用来做++i操作
private BlockingQueue<String> blockingQueue; // 阻塞队列,这里用超时的方法 offer poll
// 这里的BlockingQueue是一个接口,我们在资源类的constructor里面再定义
public ProdConsResource(BlockingQueue<String> blockingQueue) {
super();
this.blockingQueue = blockingQueue;
}
public void product() throws InterruptedException {
String data = null;
boolean ret;
while (flag) {
data = atomicInteger.incrementAndGet() + "";
ret = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
if (ret) {
System.out.println(Thread.currentThread().getName() + "进入队列" + data + "成功");
} else {
System.out.println(Thread.currentThread().getName() + "进入队列失败" + data + "失败");
}
TimeUnit.SECONDS.sleep(1);
}
}
public void consumer() throws InterruptedException {
String result = null;
while (flag) {
result = blockingQueue.poll(2, TimeUnit.SECONDS);
if (null == result || result.equalsIgnoreCase("")) {
flag = false;
System.out.println(Thread.currentThread().getName() + "超过俩秒中没有拿到蛋糕,消费停止");
return;
}
System.out.println(Thread.currentThread().getName() + "从队列中消费" + result);
}
//这个地方实现先后消费是靠sleep(1),之前是靠唤醒,这个靠时间会不会有点问题?
TimeUnit.SECONDS.sleep(1);
}
public void stop() {
this.flag = false;
}
}
public class ProdConsumerBlockQueueDemo {
public static void main(String[] args) throws InterruptedException {
ProdConsResource resource = new ProdConsResource(new ArrayBlockingQueue<String>(10));
new Thread(() -> {
try {
resource.product();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "product").start();
new Thread(() -> {
try {
resource.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "consumer").start();
TimeUnit.SECONDS.sleep(5);
System.out.println("boss拉闸");
resource.stop();
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Demo {
public static void main(String[] args) {
/*
* ExecutorService threadpool01 = Executors.newFixedThreadPool(5);
* ExecutorService threadpool02 = Executors.newSingleThreadExecutor();
* ExecutorService threadpool03 = Executors.newCachedThreadPool();
* ExecutorService threadpool04 = Executors.newScheduledThreadPool(3);
*/
ExecutorService threadpool = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(2), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
for (int i = 1; i <= 10; i++) {
threadpool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "处理了业务");
});
}
}
}
/*
* 手写一个死锁
*/
public class HoldThread {
public static void main(String[] args) {
String lockA = "AAA";
String lockB = "BBB";
new Thread(() -> {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "自己持有" + lockA + "他想要" + lockB);
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "自己持有" + lockB + "他想要" + lockA);
}
}
}, "first:").start();
new Thread(() -> {
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "自己持有" + lockB + "他想要" + lockA);
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "自己持有" + lockA + "他想要" + lockB);
}
}
}, "second:").start();
}
}
輸出:
first:自己持有AAA他想要BBB
second:自己持有BBB他想要AAA