城市分站seo,seo相关岗位,中国建设网上银行登录,网站开发 重庆1、什么是JUC
源码 官方文档 面试高频问#xff01; java.util 工具包、包、分类
业务#xff1a;普通的线程代码 Thread Runnable
Runnable 没有返回值、效率相比入 Callable 相对较低#xff01; 2、线程和进程 线程、进程#xff0c;如果不能使用一句话说出来的技术…1、什么是JUC
源码 官方文档 面试高频问 java.util 工具包、包、分类
业务普通的线程代码 Thread Runnable
Runnable 没有返回值、效率相比入 Callable 相对较低 2、线程和进程 线程、进程如果不能使用一句话说出来的技术不扎实 进程一个程序QQ.exe Music.exe 程序的集合 一个进程往往可以包含多个线程至少包含一个 Java默认有几个线程 2 个 mian、GC 线程开了一个进程 Typora写字自动保存线程负责的 对于Java而言Thread、Runnable、Callable Java 真的可以开启线程吗 开不了 并发、并行 并发编程并发、并行 并发多线程操作同一个资源
CPU 一核 模拟出来多条线程天下武功唯快不破快速交替 并行多个人一起行走CPU 多核 多个线程可以同时执行 线程池
并发编程的本质充分利用CPU的资源 线程有几个状态 public enum State {// 创建NEW,// 运行RUNNABLE,// 阻塞BLOCKED,// 等待死死地等WAITING,// 超时等待TIMED_WAITING,// 终止TERMINATED;
}wait/sleep 区别 1、来自不同的类 wait Object sleep Thread 2、关于锁的释放 wait 会释放锁sleep 睡觉了抱着锁睡觉不会释放 3、使用的范围是不同的 wait必须在同步代码块中 sleep 可以再任何地方睡 4、是否需要捕获异常 wait 不需要捕获异常 sleep 必须要捕获异常
3、Lock锁重点 传统 Synchronized package com.kuang.demo01;
// 基本的卖票例子
import java.time.OffsetDateTime;
Lock 接口
/**
* 真正的多线程开发公司中的开发降低耦合性
* 线程就是一个单独的资源类没有任何附属的操作
* 1、 属性、方法
*/
public class SaleTicketDemo01 {public static void main(String[] args) {// 并发多线程操作同一个资源类, 把资源类丢入线程Ticket ticket new Ticket();// FunctionalInterface 函数式接口jdk1.8 lambda表达式 (参数)-{ 代码 }new Thread(()-{for (int i 1; i 40 ; i) {ticket.sale();}},A).start();new Thread(()-{for (int i 1; i 40 ; i) {ticket.sale();}},B).start();new Thread(()-{for (int i 1; i 40 ; i) {ticket.sale();}},C).start();}
}
// 资源类 OOPclass Ticket {// 属性、方法private int number 30;// 卖票的方式// synchronized 本质: 队列锁public synchronized void sale(){if (number0){{System.out.println(Thread.currentThread().getName()卖出了(number--)票,剩余number);}}
}Lock 接口 可以在ReentrantLock中设置公平和非公平锁 公平锁十分公平可以先来后到 非公平锁十分不公平可以插队 默认
Lock三部曲
1. new ReentrantLock(); 2. lock.lock(); // 加锁 3. finally lock.unlock(); // 解锁 测试效果一样
Synchronized 和 Lock 区别
1.Synchronized 内置的Java关键字 Lock 是一个Java类 2.Synchronized 无法判断获取锁的状态Lock 可以判断是否获取到了锁 3.Synchronized 会自动释放锁lock 必须要手动释放锁如果不释放锁死锁 4.Synchronized 线程 1获得锁阻塞、线程2等待傻傻的等Lock锁就不一定会等待下 去 5.Synchronized 可重入锁不可以中断的非公平Lock 可重入锁可以 判断锁非公平可以 自己设置 6.Synchronized 适合锁少量的代码同步问题Lock 适合锁大量的同步代码
4、生产者和消费者问题
1Synchronzied 版本
面试的单例模式、排序算法、生产者和消费者、死锁 防止虚假唤醒要用while不能用if package com.marchsoft.juctest;public class ConsumeAndProduct {public static void main(String[] args) {Data data new Data();new Thread(() - {for (int i 0; i 10; i) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, A).start();new Thread(() - {for (int i 0; i 10; i) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, B).start();}
}class Data {private int num 0;// 1public synchronized void increment() throws InterruptedException {// 判断等待if (num ! 0) {this.wait();}num;System.out.println(Thread.currentThread().getName() num);// 通知其他线程 1 执行完毕this.notifyAll();}// -1public synchronized void decrement() throws InterruptedException {// 判断等待if (num 0) {this.wait();}num--;System.out.println(Thread.currentThread().getName() num);// 通知其他线程 -1 执行完毕this.notifyAll();}
}效果
2存在问题虚假唤醒
问题如果有四个线程会出现虚假唤醒 理解文档 重点理解if和while的线程唤醒问题
解决方式 if 改为while即可防止虚假唤醒 结论就是用if判断的话唤醒后线程会从wait之后的代码开始运行但是不会重新判断if条件直接继续运行if代码块之后的代码而如果使用while的话也会从wait之后的代码运行但是唤醒后会重新判断循环条件如果不成立再执行while代码块之后的代码块成立的话继续wait。 这也就是为什么用while而不用if的原因了因为线程被唤醒后执行开始的地方是wait之后 拿两个加法线程A、B来说比如A先执行执行时调用了wait方法那它会等待此时会释放锁那么线程B获得锁并且也会执行wait方法两个加线程一起等待被唤醒。此时减线程中的某一个线程执行完毕并且唤醒了这俩加线程那么这俩加线程不会一起执行其中A获取了锁并且加1执行完毕之后B再执行。如果是if的话那么A修改完num后B不会再去判断num的值直接会给num1。如果是while的话A执行完之后B还会去判断num的值因此就不会执行。 3JUC版 package com.marchsoft.juctest;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockCAP {public static void main(String[] args) {Data2 data new Data2();new Thread(() - {for (int i 0; i 10; i) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, A).start();new Thread(() - {for (int i 0; i 10; i) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, B).start();new Thread(() - {for (int i 0; i 10; i) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}}, C).start();new Thread(() - {for (int i 0; i 10; i) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}}, D).start();}
}class Data2 {private int num 0;Lock lock new ReentrantLock();Condition condition lock.newCondition();// 1public void increment() throws InterruptedException {lock.lock();try {// 判断等待while (num ! 0) {condition.await();}num;System.out.println(Thread.currentThread().getName() num);// 通知其他线程 1 执行完毕condition.signalAll();}finally {lock.unlock();}}// -1public void decrement() throws InterruptedException {lock.lock();try {// 判断等待while (num 0) {condition.await();}num--;System.out.println(Thread.currentThread().getName() num);// 通知其他线程 1 执行完毕condition.signalAll();}finally {lock.unlock();}}
}
随机执行 Condition的优势
精准的通知和唤醒的线程
如何指定线程执行的顺序 我们可以使用Condition来指定通知进程~
package com.marchsoft.juctest;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ConditionDemo {public static void main(String[] args) {Data3 data3 new Data3();new Thread(() - {for (int i 0; i 10; i) {data3.printA();}},A).start();new Thread(() - {for (int i 0; i 10; i) {data3.printB();}},B).start();new Thread(() - {for (int i 0; i 10; i) {data3.printC();}},C).start();}}
class Data3 {private Lock lock new ReentrantLock();private Condition condition1 lock.newCondition();private Condition condition2 lock.newCondition();private Condition condition3 lock.newCondition();private int num 1; // 1A 2B 3Cpublic void printA() {lock.lock();try {// 业务代码 判断 - 执行 - 通知while (num ! 1) {condition1.await();}System.out.println(Thread.currentThread().getName() AAAA );num 2;condition2.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}public void printB() {lock.lock();try {// 业务代码 判断 - 执行 - 通知while (num ! 2) {condition2.await();}System.out.println(Thread.currentThread().getName() BBBB );num 3;condition3.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}public void printC() {lock.lock();try {// 业务代码 判断 - 执行 - 通知while (num ! 3) {condition3.await();}System.out.println(Thread.currentThread().getName() CCCC );num 1;condition1.signal();}catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}
}测试效果
JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题 的学习笔记到此完结笔者归纳、创作不易大佬们给个3连再起飞吧