Lock
实现类
ReentrantLock();
构造方法
NonfairSync();非公平锁
FairSync();公平锁 可以先来后到
lock和synchronized的区别
synchronized | lock |
---|---|
java关键字 | java类 |
无法判断锁的状态 | 可以判断是否获取到了锁 |
会自动释放锁 | lock锁需要手动释放(不释放会死锁) |
线程获取到不到锁会一直等待 | lock.tryLock() 可以尝试获取锁,可设置超时时间 |
可重入锁,不可中断,非公平 | 可重入锁,可以设置是否公平锁 |
适合锁少量代码同步问题 | 适合锁大量同步代码块 |
synchronized和lock锁实现卖票问题
package com.yunwangl.juc.ticket;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
/**
* @ClassName SellTicket
* @Description
* @Author LiuQunYu
* @Date 2021/3/22 21:06
* @Version V1.0
**/
public class SellTicket {
public static void main(String[] args) {
// synchronizedSell(); // synchronized关键词实现
LockSell(); // lock锁实现
}
public static void LockSell() {
TicketLock ticket = new TicketLock();
Stream.of("线程1", "线程2", "线程3", "线程4", "线程5").forEach(name -> {
new Thread(() -> {
while (ticket.num > 0) {
ticket.sell();
}
}, name).start();
});
}
static class TicketLock {
private Lock lock = new ReentrantLock();
private int num = 1000;
public void sell() {
lock.lock();
try {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + this.num-- + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void synchronizedSell() {
Ticket ticket = new Ticket();
Stream.of("线程1", "线程2", "线程3", "线程4", "线程5").forEach(name -> {
new Thread(() -> {
while (ticket.num > 0) {
ticket.sell();
}
}, name).start();
});
}
static class Ticket {
private int num = 1000;
public synchronized void sell() {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + this.num-- + "张票");
}
}
}
}
消费者生产者问题
线程等待避免使用if 应使用while循环判断
synchronized 线程等待
this.wait();
唤醒线程
this.notifyAll();
lock锁实现
final Condition condition = lock.newCondition();
condition.await();
condition.signalAll();
package com.yunwangl.juc.consumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
/**
* @ClassName Demo
* @Description
* @Author LiuQunYu
* @Date 2021/3/23 0:15
* @Version V1.0
**/
public class Demo {
public static void main(String[] args) {
// synchronizedDataPC();
// lockDataPC();
OrderPrintMethod();
}
/**
* synchronized 实现消费者生产者问题
*/
public static void synchronizedDataPC() {
Data data = new Data();
Stream.of("生产者线程1", "生产者线程2", "生产者线程3").forEach(name -> {
new Thread(() -> {
while (true) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, name).start();
});
Stream.of("消费者线程1", "消费者线程2", "消费者线程3").forEach(name -> {
new Thread(() -> {
while (true) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, name).start();
});
}
/**
* synchronized 具体业务类
*/
static class Data {
private int num = 0;
public synchronized void increment() throws InterruptedException {
while (num != 0) {
// 等待消费
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "生产数据->" + num);
// 生产数据完成 通知消费者消费
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
while (num == 0) {
// 等待生产者生产
this.wait();
}
// 消费数据
num--;
System.out.println(Thread.currentThread().getName() + "消费数据->" + num);
// 通知生产者生产数据
this.notifyAll();
}
}
/**
* lock锁实现简单消费者生产者问题
*/
public static void lockDataPC() {
LockData data = new LockData();
Stream.of("生产者线程1", "生产者线程2", "生产者线程3").forEach(name -> {
new Thread(() -> {
while (true) {
data.increment();
}
}, name).start();
});
Stream.of("消费者线程1", "消费者线程2", "消费者线程3").forEach(name -> {
new Thread(() -> {
while (true) {
data.decrement();
}
}, name).start();
});
}
/**
* lock锁具体业务类
*/
static class LockData {
Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
private int num = 0;
public void increment() {
lock.lock();
try {
while (num != 0) {
// 等待消费
condition.await();
}
// 生产数据
num++;
System.out.println(Thread.currentThread().getName() + "生产数据->" + num);
// 生产数据完成 通知消费者消费
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
while (num == 0) {
// 等待生产者生产
condition.await();
}
// 消费数据
num--;
System.out.println(Thread.currentThread().getName() + "消费数据->" + num);
// 通知生产者生产数据
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
static void OrderPrintMethod() {
OrderPrintData orderPrintData = new OrderPrintData();
new Thread(() -> {
while (true) {
orderPrintData.print1();
}
}, "线程1").start();
new Thread(() -> {
while (true) {
orderPrintData.print2();
}
}, "线程2").start();
new Thread(() -> {
while (true) {
orderPrintData.print3();
}
}, "线程3").start();
}
/**
* lock锁实现线程顺序打印依次执行
*/
static class OrderPrintData {
Lock lock = new ReentrantLock();
final Condition condition1 = lock.newCondition();
final Condition condition2 = lock.newCondition();
final Condition condition3 = lock.newCondition();
private int num = 1;
public void print1() {
lock.lock();
try {
while (num != 1) {
// 等待
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "打印->" + num);
num = 2;
// 通知其他线程
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print2() {
lock.lock();
try {
while (num != 2) {
// 等待
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "打印->" + num);
num = 3;
// 通知其他线程
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print3() {
lock.lock();
try {
while (num != 3) {
// 等待消费
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "打印->" + num);
num = 1;
// 通知其他线程
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
锁问题 synchronized
没有被synchronized修饰的方法不受锁的影响
修饰类型 | 锁的目标 |
---|---|
修饰普通方法 | 锁对象 |
修饰static方法 | 锁类 |
修饰普通成员变量 | 锁对象 |
修饰static成员变量 | 锁类 |
集合并发修改问题
类名 | 方法 |
---|---|
ArrayList | |
Vector | |
Collections.synchronizedList() | |
CopyOnWriteArrayList |
package com.yunwangl.juc.list;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @ClassName Demo
* @Description 多线程并发集合修改问题
* @Author LiuQunYu
* @Date 2021/3/26 0:04
* @Version V1.0
**/
public class Demo {
public static void main(String[] args) {
// concurrenceList();
// concurrenceVector();
// concurrenceSyList();
concurrenceCopyOnWriteList();
}
/**
* list 并发操作测试
*
* 发生ConcurrentModificationException 并发修改异常
*/
static void concurrenceList() {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
list.add(String.valueOf(UUID.randomUUID()));
System.out.println(list);
}).start();
}
}
/**
* 使用Vector集合解决并发修改异常问题 底层使用synchronized
*/
static void concurrenceVector(){
List<String> list = new Vector<>();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
list.add(String.valueOf(UUID.randomUUID()));
System.out.println(list);
}).start();
}
}
/**
* 使用集合工具Collections.synchronizedList 底层为内部类new SynchronizedList<>(list));
* <p>
* public boolean add(E e) {
* synchronized (mutex) {return c.add(e);}
* }
* </p>
*/
static void concurrenceSyList(){
List<String> list = Collections.synchronizedList(new ArrayList<String>());
for (int i = 0; i < 10; i++) {
new Thread(() -> {
list.add(String.valueOf(UUID.randomUUID()));
System.out.println(list);
}).start();
}
}
/**
* 底层实现 private transient volatile Object[] array;
*/
static void concurrenceCopyOnWriteList(){
List<String> list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
list.add(String.valueOf(UUID.randomUUID()));
System.out.println(list);
}).start();
}
}
}
线程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
volatile关键词