多线程进阶=>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 list = new Vector<>();
		* 2、List list = Collections.synchronizedList(new ArrayList<>
		());
		* 3、List 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();
		}
	}
}

你可能感兴趣的:(多线程进阶=>JUC并发编程)