狂神 JUC笔记
2. 进程和线程
// 本地方法,底层的C++,java无法直接操作硬件
private native void start0();
-
查看CPU核数的方法
-
任务管理器 - 性能 - CPU
-
我的电脑-右键管理-设备管理器-处理器
-
-
线程有几个状态
public enum State {
// 新生
NEW,
// 运行
RUNNABLE,
// 阻塞
BLOCKED,
// 等待
WAITING,
// 超时等待
TIMED_WAITING,
// 终止
TERMINATED;
}
3. Lock锁
-
idea 快捷键
Ctrl + Alt +T
公平锁:先来的先执行
非公平锁:十分不公平,可以插队(默认)
-
Synchronized
package com.xiaofan;
public class SaleTicketDemo01 {
public static void main(String[] args) {
// 并发: 多线程操作同一个资源类, 把资源类丢入线程
final Ticket ticket = new Ticket();
// @FunctionalInterface 函数式接口, jdk1.8 lambda 表达式(参数)->{代码}
new Thread(()->{ for (int i = 0; i < 31; i++) ticket.sale(); }, "A").start();
new Thread(()->{ for (int i = 0; i < 31; i++) ticket.sale(); }, "B").start();
new Thread(()->{ for (int i = 0; i < 31; i++) ticket.sale(); }, "C").start();
}
}
// 资源类 OOP
class Ticket {
// 属性,方法
private int number = 30;
// 卖票的方式
public synchronized void sale() {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "张票, 剩余票数:" + number);
}
}
}
-
Lock
package com.xiaofan;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SaleTicketDemo02 {
public static void main(String[] args) {
// 并发: 多线程操作同一个资源类, 把资源类丢入线程
final Ticket2 ticket2 = new Ticket2();
// @FunctionalInterface 函数式接口, jdk1.8 lambda 表达式(参数)->{代码}
new Thread(()->{ for (int i = 0; i < 31; i++) ticket2.sale(); }, "A").start();
new Thread(()->{ for (int i = 0; i < 31; i++) ticket2.sale(); }, "B").start();
new Thread(()->{ for (int i = 0; i < 31; i++) ticket2.sale(); }, "C").start();
}
}
// Lock三部曲
// 1. new ReentrantLock();
// 2. lock.lock();
// 3. lock.unlock(); 解锁
class Ticket2 {
// 属性,方法
private int number = 30;
private 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();
}
}
}
-
Synchronized 和 Lock的区别
-
Synchronized 内置的Java关键字, Lock是一个Java类
-
Synchronized 无法判断获取锁的状态, Lock可以判断是否获取到了锁
-
Synchronized 会自动释放锁, Lock必须要手动释放锁,如果不释放锁,死锁!
-
Synchronized 线程1(获得锁,阻塞)、线程2(等待,傻傻的等);Lock锁就不一定会等待下去
-
Synchronized 可重入锁,不可以中断的,非公平锁;Lock,可重入锁,可以判断锁,非公平锁(可自己设置)
-
Synchronized 适合锁少量的代码同步问题, Lock适合锁大量的同步代码!
-
4. 生产者和消费者
4.1. 生产者和消费者问题Synchronized版
面试手写的: 单例模式、排序算法、生产者和消费者、死锁
package com.xiaofan.pc;
/**
* 线程之间的通信问题: 生产者和消费者问题! 等待环形, 通知唤醒
* 线程交替执行 A B 操作同一个变量 num = 0
* A num + 1
* B num - 1
*/
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "B").start();
}
}
// 判断等待, 业务, 通知
class Data {
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
if (number != 0) {
this.wait();
}
number ++;
System.out.println(Thread.currentThread().getName() + " => " + number);
// 通知其他线程, 我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();
}
number --;
System.out.println(Thread.currentThread().getName() + " => " + number);
// 通知其他线程, 我+1完毕了
this.notifyAll();
}
}
-
问题存在,A,B,C,D 四个线程!
package com.xiaofan.pc;
/**
* 线程之间的通信问题: 生产者和消费者问题! 等待环形, 通知唤醒
* 线程交替执行 A B 操作同一个变量 num = 0
* A num + 1
* B num - 1
*/
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "B").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "C").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "D").start();
}
}
// 判断等待, 业务, 通知
class Data {
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
while (number != 0) {
this.wait();
}
number ++;
System.out.println(Thread.currentThread().getName() + " => " + number);
// 通知其他线程, 我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number == 0) {
this.wait();
}
number