JUC并发编程笔记
juc并发编程
1、回顾
1、并发 并行
并发(多个线程操作同一个资源)
-
CPU一核,一次只能执行一个线程,所以就模拟多个线程同时进行;这就出现了:操作系统的调度:时间片轮转
并行(真正的同时进行):
-
基于CPU多核,多个线程同时进行:线程池
public class Test01 {
public static void main(String[] args) {
//获取CPU核数
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
2、wait sleep区别
1、来自不同类
wait-->Object
sleep-->Thread
2、关于释放锁
wait()释放,sleep不释放
3、使用的范围
wait 必须在同步代码块中
sleep可以在任何地方
4、是否需要捕获异常
wait不需要捕获异常
sleep必需捕获异常
2、Lock锁(重点)
Synchronized
用synchronized解决买票问题
public class Test02 {
public static void main(String[] args) {
Ticket1 ticket1 = new Ticket1();
//lamod表达式
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket1.sale();
}
},"窗口A").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket1.sale();
}
},"窗口B").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket1.sale();
}
},"窗口C").start();
}
}
//线程共享得就是一个单独资源,尽量减少耦合
class Ticket1{
private int num=30;
//加synchronized 自动
public synchronized void sale(){
if (num>0){
System.out.println(Thread.currentThread().getName()+"买了第"+num+"张票");
num--;
}
}
}
Lock
用lock解决买票问题
public class Test03 {
public static void main(String[] args) {
Ticket2 ticket2 = new Ticket2();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
},"b").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
},"c").start();
}
}
class Ticket2{
private int num=30;
//手动
private ReentrantLock lock = new ReentrantLock();
public void sale(){
//加锁就必须i解锁 必须是成对出现
lock.lock();//加锁
try{
if (num>0){
System.out.println(Thread.currentThread().getName()+"买了第"+num+"张票");
num--;
}
}catch (Exception e){
}finally {
lock.unlock();//解锁
}
}
}
Synchronized 和 Lock的区别
1、Synchronized是内置的关键字,Lock是对象
2、Synchronized无法判断获取锁的状态,Lock可以判断是否获得了锁
3、synchronized会自动释放锁,Lock必须手动释放锁:不释放就死锁
4、Synchronized 线程1获得锁的时候,线程2只能等。Lock就不一定(tryLock()尝试获取锁)
5、Synchronized 可重入锁,不可以中断的,非公平。Lock,可重入,可判断锁的状态,自己设置是否公平
6、Synchronized 适合锁少量代码块 Lock大量
啥是锁? 怎么判断锁的是谁?
3、生产者消费者问题
加一个减一个
synchronized版
public class Test04 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"a").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"b").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"c").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"a").start();
}
}
//等待,业务,通知
class Data{
int num=0;
synchronized void increment() throws InterruptedException {
//此处要循环判断,防止虚假唤醒
while (num!=0){
//等待
this.wait();
}
num+=1;
System.out.println(Thread.currentThread().getName()+"getNum->"+num);
//通知
this.notifyAll();
}
synchronized void decrement() throws InterruptedException {
while(num==0){
this.wait();
}
num-=1;
System.out.println(Thread.currentThread().getName()+"getNum->"+num);
this.notifyAll();
}
}
Lock(JUC)版
public class Test05 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"a").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"b").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"c").start();
new Thread(()->{
try {
for (int i = 0; i < 6; i++) {
data.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"d").start();
}
}
//等待,业务,通知
class Data2{
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int num=0;
void increment() throws InterruptedException{
//此处要循环判断,防止虚假唤醒
lock.lock();
try {
while (num!=0){
//等待
condition.await();
}
num+=1;
System.out.println(Thread.currentThread().getName()+"getNum->"+num);
//通知
condition.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
void decrement() throws InterruptedException {
lock.lock();
try {
while(num==0){
condition.await();