Java语言基础
多线程
一、线程死锁
1. 概述
死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进,导致两个或者多个线程都在等待对方释放资源 , 都停止执行的情形;死锁不仅仅在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,指两个或多个线程之间,由于互相持有对方需要的锁,互相等待,而永久处于阻塞状态。
2. 演示
这个程序由于线程出现死锁,故一直处于运行状态
public class ThreadDeadLock {
public static void main(String[] args) {
DeadLockA deadLockA = new DeadLockA();
Thread threadA = new Thread(deadLockA, "线程1");
DeadLockB deadLockB = new DeadLockB();
Thread threadB = new Thread(deadLockB, "线程2");
threadA.start();
threadB.start();
}
}
class DeadLockA implements Runnable {
@Override
public void run() {
synchronized ("A") {
System.out.println(Thread.currentThread().getName() + "持有了A锁,等待B锁。。。");
synchronized ("B") {
System.out.println(Thread.currentThread().getName() + "持有了A锁和B锁");
}
}
}
}
class DeadLockB implements Runnable {
@Override
public void run() {
synchronized ("B") {
System.out.println(Thread.currentThread().getName() + "持有了B锁,等待A锁。。。");
synchronized ("A") {
System.out.println(Thread.currentThread().getName() + "持有了B锁和A锁");
}
}
}
}
3. 死锁发生的条件
(1)互斥条件:一个资源每次只能被一个进程使用。
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不剥夺条件: 进程已获得的资源,在未使用完之前,不能强行剥夺。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
4. 解决方法
wait(): 表示线程一直等待 , 直到其他线程通知 , 与sleep不同 , 会释放锁
wait(long timeout): 指定等待的毫秒数
notify(): 唤醒一个处于等待状态的线程
notifyAll(): 唤醒同一个对象上所有调用wait()方法的线程 , 优先级 别高的线程优先调度
二、 线程协调之生产者&消费者模式
多线程环境下,我们经常需要多个线程的并发和协作。这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”。
生产者:指的是负责生产数据的模块(这里模块可能是:方法、对象、线程、进程)。
消费者:指的是负责处理数据的模块(这里模块可能是:方法、对象、线程、进程)。
缓冲区:消费者不能直接使用生产者的数据,它们之间有个“缓冲区”。生产者将生产好的数据放入“缓冲区”,消费者从“缓冲区”拿要处理的数据。
//产品/食物
public class Product {
public String name;
public Product(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//缓冲区/柜台大小
import java.util.List;
public class ProductPool {
//定义缓冲区大小为8
public int maxsize=8;
//产品的列表
public List <Product> list;
public ProductPool(int maxsize, List<Product> list) {
this.maxsize = maxsize;
this.list = list;
}
//生产者生产产品,放入产品到缓冲区
public synchronized void push(Product product){
if (this.list.size()>=this.maxsize){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生产者生产了一个产品
this.list.add(product);
// 通知消费者消费。
this.notifyAll();
}
//消费者消费产品,从缓冲区移除产品
public synchronized Product pop(){
// 产品数量不能小于0
// 如果小于0,就等待生产者生产产品。
if (this.list.size()<=0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消费者消费了一个产品
Product product = this.list.remove(0);
// 通知生产者生产产品。
this.notifyAll();
return product;
}
}
//生产者/厨师
public class Producer implements Runnable
public ProductPool productPool;
public Producer(ProductPool productPool) {
this.productPool = productPool;
}
@Override
public void run() {
int i=1;
while (true){
Product product = new Product("产品名称" + i++);
this.productPool.push(product);
System.out.println("生产者生产了产品:" + product.getName());
}
}
}
//消费者/顾客
public class Consumer implements Runnable {
public ProductPool productPool;
public Consumer(ProductPool productPool) {
this.productPool = productPool;
}
//模拟消费者消费产品
@Override
public void run() {
while (true){
Product product = this.productPool.pop();
System.out.println("消费者消费了产品:" + product.getName());
}
}
}
//生产者消费者模式
public class MyTest {
public static void main(String[] args) {
ProductPool productPool = new ProductPool(8, new LinkedList<>());
Producer producer = new Producer(productPool);
Thread thread = new Thread(producer);
thread.start();
Consumer consumer = new Consumer(productPool);
Thread thread1 = new Thread(consumer);
thread1.start();
}
}
/*
生产者生产了产品:产品名称1
生产者生产了产品:产品名称2
生产者生产了产品:产品名称3
生产者生产了产品:产品名称4
生产者生产了产品:产品名称5
生产者生产了产品:产品名称6
生产者生产了产品:产品名称7
生产者生产了产品:产品名称8
消费者消费了产品:产品名称1
消费者消费了产品:产品名称2
消费者消费了产品:产品名称3
消费者消费了产品:产品名称4
消费者消费了产品:产品名称5
消费者消费了产品:产品名称6
消费者消费了产品:产品名称7
消费者消费了产品:产品名称8
生产者生产了产品:产品名称9
...
*/
//未完待续,后面补充…