【学习笔记】JUC并发编程
教学视频地址:B站尚硅谷JUC并发编程教学视频
代码:实例程序
文章目录
一、JUC简介
一些基本概念:
串行:一个一个执行
管程:monitor监视类,就是平时所说的“锁”
二、Lock接口
1、synchronize
略,详细看之前写的 java基础-多线程 代码
2、Lock
略,详细看之前写的 java基础-多线程 代码
三、线程间的通讯
就是生产者消费者问题 中的那个缓冲池 实现了线程之间的通讯
多线程并发线程步骤:
1、创建共享资源
2、创建并发执行的方法:上锁、判断临界条件、实现逻辑、通知其他进程、解锁
- sinal的使用
await()、signal()、signalAll():
Condition在Java 1.5 中出现,用来代替传统的wait()、notify()、notifyAll()方法,相比于wait()、notify()、notifyAll()方法,await()、signal()、signalAll()更加安全和高效。
wait()、notify()、notifyAll()方法分别对应于Condition中的await()、signal()、signalAll()。
Condition简单介绍:
1、Condition是个接口,基本的方法就是await()和signal()方法;
2、调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
四、线程间的定制化通信
- 引入
- 代码
五、集合的线程安全
- 不安全演示
- 解决方法一
- 方法二
- 方法三
写时复制技术:
同个进程同时写同时读,没有人要写时则正常读,有人要写则复制一份出来写入新内容,然后再和旧内容合并、覆盖,之后在读取合并后的内容
六、多线程锁
- synchronize的八种情况
详细例子看代码 - 公平锁和非公平锁
优缺点:
- 可重入锁
获得一把锁后可以重复进入用这把锁加锁的所有区域
- 死锁
基本内容略
检查是否发生死锁(java bin里的jsp.exe配到环境变量里)
七、Callable接口
即是创建线程的其中一种方式,略
八、辅助类
- 减少计数类countDownLath
从x减少到0才可以继续执行
引入
代码:
public class Test {
public static void main(String[] args) throws InterruptedException {
//创建技术类
CountDownLatch countDownLatch = new CountDownLatch(6);
//六个同学陆续离开教室
for (int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 离开");
//离开后,计数器减一
countDownLatch.countDown();
},String.valueOf(i)).start();
}
//班长锁门,并发顺序不对
System.out.println("错误锁门----");
//计数器为零之前让其阻塞
countDownLatch.await();
System.out.println("正确锁门-----");
}
}
- 循环栅栏
从零增加到x才可以执行特定代码
引入:找到七颗龙珠才可以召唤神龙
代码:
public class Test {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("召唤神龙!!!!!");
});
for (int i = 1; i < 8; i++) {
new Thread(()->{
System.out.println("第"+Thread.currentThread().getName()+"颗龙珠被搜集。。。。");
//没搜集完成就阻塞
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
- 信号量
略
代码:
public class Test {
public static void main(String[] args) {
//三个车位六辆车
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i < 7; i++) {
new Thread(()->{
//申请信号量
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"抢到车位...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放信号量
semaphore.release();
System.out.println("---"+Thread.currentThread().getName()+"离开车位...");
}
},String.valueOf(i)).start();
}
}
}
九、读写锁
悲观锁:完全上锁,不支持并发
乐观锁:同时操作时加上版本被标记,最后再合并,冲突则回退,支持并发
表锁:对一张表中的一条数据操作,将整张表上锁
行锁:对一张表中的一条数据操作,只上锁这一条数据,会发生死锁
读锁:共享锁,会发生死锁
写锁:独占锁(排他锁),会发生死锁
读写锁代码:
//资源类
class MyCache{
//创建读写锁
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public volatile HashMap<String, String> hashMap = new HashMap<>();
public void put(String key,String value) throws InterruptedException {
try {
//上锁
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName()+" 正在进行写操作...");
hashMap.put(key,value);
//时停
// TimeUnit.SECONDS.sleep(100);
System.out.println(Thread.currentThread().getName()+" 写操作已完成...");
}finally {
//解锁
readWriteLock.writeLock().unlock();
}
}
public String get(String key) throws InterruptedException {
String s = null;
try {
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName()+" 正在进行读操作...");
s = hashMap.get(key);
//时停
// TimeUnit.SECONDS.sleep(100);
System.out.println(Thread.currentThread().getName()+" 读操作已完成...");
}finally {
readWriteLock.readLock().unlock();
}
return s;
}
}
锁降级:
十、阻塞队列
- 基本概念
- 分类
- 核心方法
- 代码
public static void main(String[] args) throws InterruptedException {
//长度为三的数组阻塞队列
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println("-------------第一组---------------");
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
// System.out.println(blockingQueue.add("d"));
System.out.println("检查:"+blockingQueue.element());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
System.out.println("-------------第二组---------------");
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("d"));
System.out.println("检查:"+blockingQueue.peek());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println("-------------第三组---------------");
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take());
System.out.println("-------------第四组-----------------");
System.out.println(blockingQueue.offer("a",2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("b",2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("c",2, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("d",2, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
}
十一、ThreadPool线程池
-
基本概念
略 -
使用方式
-
七个参数
- 处理流程
- 代码
public static void main(String[] args) {
//一池多线程
// ExecutorService threadPool = Executors.newFixedThreadPool(3);
//一池一线程
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
//可扩充线程池
// ExecutorService threadPool = Executors.newCachedThreadPool();
//自定义线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
5,
2,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(4),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 0; i < 10; i++) {
//执行十个线程
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
threadPool.shutdown();
}
}
十二、fork/jion分支合并框架
- 基本概念
- 实例