多线程进阶=>JUC并发编程

并发编程的本质:充分利用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:卖票例子

/**
* 真正的多线程开发,公司中的开发,降低耦合性
* 线程就是一个单独的资源类,没有任何附属的操作!
* 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();
				}
		}
		// 资源类 OOP
	class Ticket {
		// 属性、方法
		private int number = 30;
		// 卖票的方式
		// synchronized 本质: 队列,锁
		public synchronized void sale(){
			if (number>0){
			System.out.println(Thread.currentThread().getName()+"卖出了"+(number-
			-)+"票,剩余:"+number);
			}
			}
	}

Lock 接口
公平锁:十分公平:可以先来后到
非公平锁:十分不公平:可以插队 (默认)

public class SaleTicketDemo02 {
	public static void main(String[] args) {
	// 并发:多线程操作同一个资源类, 把资源类丢入线程
		Ticket2 ticket = new Ticket2();
		// @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();
		}
	}
// Lock三部曲
// 1、 new ReentrantLock();
// 2、 lock.lock(); // 加锁
// 3、 finally=> lock.unlock(); // 解锁
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(); // 解锁
	}
}
}

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、生产者和消费者问题

面试的:单例模式、排序算法、生产者和消费者、死锁
生产者和消费者问题 Synchronized 版

public class A {
	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 number = 0;
		//+1
		public synchronized void increment() throws InterruptedException {
		if (number!=0){ //0
			// 等待
			this.wait();
		}
		number++;
		System.out.println(Thread.currentThread().getName()+"=>"+number);
		// 通知其他线程,我+1完毕了
		this.notifyAll();
	}
	//-1
	public synchronized void decrement() throws InterruptedException {
	if (number==0){ // 1
	// 等待
		this.wait();
	}
	number--;
	System.out.println(Thread.currentThread().getName()+"=>"+number);
	// 通知其他线程,我-1完毕了
	this.notifyAll();
	}
}

问题存在,A B C D 4 个线程! 虚假唤醒,等待应该总是出现在循环中,if 改为 while 判断。

/**
* 线程之间的通信问题:生产者和消费者问题! 等待唤醒,通知唤醒
* 线程交替执行 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(()->{
		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 number = 0;
	//+1
	public synchronized void increment() throws InterruptedException {
		while (number!=0){ //0
			// 等待
			this.wait();
	}
	number++;
	System.out.println(Thread.currentThread().getName()+"=>"+number);
	// 通知其他线程,我+1完毕了
	this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
	while (number==0){ // 1
		// 等待
		this.wait();
	}
	number--;
	System.out.println(Thread.currentThread().getName()+"=>"+number);
	// 通知其他线程,我-1完毕了
	this.notifyAll();
	}
}

Condition 精准的通知和唤醒线程

public class C {
	public static void main(String[] args) {
		Data3 data = new Data3();
		new Thread(()->{
		``for (int i = 0; i <10 ; i++) {
			data.printA();
		}
		},"A").start();
		new Thread(()->{
			for (int i = 0; i <10 ; i++) {
				data.printB();
		}
		},"B").start();
		new Thread(()->{
			for (int i = 0; i <10 ; i++) {
				data.printC();
			}
		},"C").start();
	}
}
class Data3{ // 资源类 Lock
	private Lock lock = new ReentrantLock();
	private Condition condition1 = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	private Condition condition3 = lock.newCondition();
	private int number = 1; // 1A 2B 3C
	public void printA(){
		lock.lock();
		try {
		// 业务,判断-> 执行-> 通知
		while (number!=1){
		// 等待
		condition1.await();
		}
		System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
	// 唤醒,唤醒指定的人,B
	number = 2;
		condition2.signal();
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
	lock.unlock();
	}
	}
	public void printB(){
		lock.lock();
		try {
			// 业务,判断-> 执行-> 通知
			while (number!=2){
		condition2.await();
		}
		System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
		// 唤醒,唤醒指定的人,c
		number = 3;
			condition3.signal();`
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
	}
}
public void printC(){
	lock.lock();
	try {
	// 业务,判断-> 执行-> 通知
	// 业务,判断-> 执行-> 通知
		while (number!=3){
			condition3.await();
	}
	System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
	// 唤醒,唤醒指定的人,c
			number = 1;
			condition1.signal();
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		lock.unlock();
	}
	}
}

```java
在这里插入代码片

深刻理解我们的锁

new this 具体的一个类
static Class 唯一的一个模板

6、集合类不安全

list不安全

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
// java.util.ConcurrentModificationException 并发修改异常!
public class ListTest {
	public static void main(String[] args) {
		// 并发下 ArrayList 不安全的吗,Synchronized;
		/**
		* 解决方案;
		* 1、List<String> list = new Vector<>();
		* 2、List<String> list = Collections.synchronizedList(new ArrayList<>
		());
		* 3、List<String> list = new CopyOnWriteArrayList<>();
		*/
		// CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略;
		// 多个线程调用的时候,list,读取的时候,固定的,写入(覆盖)
		// 在写入的时候避免覆盖,造成数据问题!
		// 读写分离
		// CopyOnWriteArrayList 比 Vector Nb 在哪里?
		List<String> list = new CopyOnWriteArrayList<>();
		for (int i = 1; i <= 10; i++) {
			new Thread(()->{
				list.add(UUID.randomUUID().toString().substring(0,5));
				System.out.println(list);
			},String.valueOf(i)).start();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值