JUC
1.什么是JUC
Java.util:java工具包
Runnable :没有返回值.效率比calllable来看要低一点
InterfaceLock
线程与进程
进程:程序的集合
一个进程可以包含多个线程,自少包含一个
java默认有两个线程,main、GC
线程:代码的集合
java线程:Thread、Runnable、callable
java真的可以开启线程嘛?不可以
最终是一个native方法,调用底层的C++,java无法直接操作硬件
并发、并行
并发:多线程操作同一个资源,间歇性
并行:多个线程一起走;线程池
public class Test1 {
public static void main(String[] args) {
//获取cpu核数
//cpu密集型,IO密集型
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
并发的本质:充分利用cpu资源
2.多线程
线程几个状态
NEW,//新建
RUNNABLE,//运行
BLOCKED,//组塞
WAITING,//等待
TIMED_WAITING,//超时等待
TERMINATED;//终止
wait/sleep区别
来自不同类
wait=>Object
sleep=>Thread
锁的释放不一样
wait释放
sleep抱着锁睡觉不释放
使用范围不一样
wait要在同步代码块
sleep可以在任何地方
是否捕获异常
wait不需要
sleep一定要
3.LOCK锁
传统Synchronize
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRhOlitG-1651493924827)(JUC.assets/image-20220502172232364.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoVP8exY-1651493924828)(JUC.assets/image-20220502172352328.png)]
公平锁与非公平锁
公平锁:先来后到
非公平锁:可以插队
默认为非公平锁
Synchronize与LOCK区别
- Synchronize是内置的一个关键字,lock是一个java类
- Synchronize无法获取锁的状态,lock可以判断是否获取到了锁
- Synchronize会自动释放锁,lock必须要手动释放,如果不释放就成为了死锁
- Synchronize线程1(获得锁,阻塞)、线程2(等待,傻等);lock不会一直等待下去
锁是什么
生产者和消费者问题
package com.shiyi.produnctCons;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SaleTicketDemo02 {
public static void main(String[] args) {
final Ticket2 ticket = new Ticket2();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"C").start();
}
}
// 资源类 OOP 属性、方法
class Ticket2 {
private int number = 30;
Lock lock=new ReentrantLock();
//卖票的方式
public void sale() {
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "张票剩余" + number + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
存在问题
package com.shiyi.produnctCons;
/*
线程之间的通信问题:生产者和消费者问题
线程交替执行 A B操作同一个变量 num=0 A让num+1,B让num-1;
**/
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();
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 Data {
private int num = 0;
// +1
public synchronized void increment() throws InterruptedException {
// 判断等待
if (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "=>" + num);
// 通知其他线程 +1 执行完毕
this.notifyAll();
}
// -1
public synchronized void decrement() throws InterruptedException {
// 判断等待
if (num == 0) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + "=>" + num);
// 通知其他线程 -1 执行完毕
this.notifyAll();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WXEMUudK-1651493924829)(JUC.assets/image-20220502191806639.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BCruekuq-1651493924830)(JUC.assets/image-20220502191813533.png)]
如何解决虚假唤醒问题,使用while进行判断
package com.shiyi.produnctCons;
/*
线程之间的通信问题:生产者和消费者问题
线程交替执行 A B操作同一个变量 num=0 A让num+1,B让num-1;
**/
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();
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 Data {
private int num = 0;
// +1
public synchronized void increment() throws InterruptedException {
// 判断等待
while (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "=>" + num);
// 通知其他线程 +1 执行完毕
this.notifyAll();
}
// -1
public synchronized void decrement() throws InterruptedException {
// 判断等待
while (num == 0) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + "=>" + num);
// 通知其他线程 -1 执行完毕
this.notifyAll();
}
}