多线程3

1. 线程阻塞

  1. 同步阻塞
  2. 调用sleep(),join()方法的时候,sleep()转为休眠,时间到自动唤醒
  3. wait(),notify()方法配套,转为等待,同时释放资源,通过notify()方法唤醒

  4. yield(),释放资源,与其他线程重新抢占资源,抢到就执行

  5. suspend()和resume(),由jdk1.0提供,jdk1.2之后就被放弃了,它也是让线程暂停,但是它不释放资源,导致死锁出现

2. 线程死锁

死锁产生的必要条件:

​ 1>互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

​ 2>不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

​ 3>请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占用。

​ 4>循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路

​ 在我们的项目中,我们不希望看到死锁的发生,为了避免,以上四个条件,破坏其中任意一个,死锁就结束了

​ 注意:过多的同步会导致死锁

死锁示例如下:

public class MyRun implements Runnable {
	private static Object a = new Object();
	private static Object b = new Object();
	private boolean flag = true;

	public void changeFlag() {
		flag = false;
	}

	@Override
	public void run() {
		if (flag) {
			synchronized (a) {
				System.out.println(Thread.currentThread().getName() + "锁定了资源a");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (b) {
					System.out.println(Thread.currentThread().getName() + "锁定资源b");
				}
			}
		} else {
			synchronized (b) {
				System.out.println(Thread.currentThread().getName() + "锁定了资源b");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (a) {
					System.out.println(Thread.currentThread().getName() + "锁定资源a");
				}
			}
		}
	}
}
测试如下:
public class Test {
	public static void main(String[] args) {
		MyRun mra = new MyRun();
		new Thread(mra, "线程1").start();
		MyRun mrb = new MyRun();
		mrb.changeFlag();
		new Thread(mrb, "线程2").start();
	}
}
 

3. Object对线程的支持

wait():让线程暂停执行,进入阻塞状态,要求必须有synchronized来修饰

notify():把阻塞的线程唤醒,这里唤醒的是针对wait()阻塞的线程,如果有多个阻塞的,只唤醒第一个

notifyAll():唤醒所有的

以上三个方法,都是针对同一个对象

wait()与sleep()的差别:

  1. wait是属于Object类提供的方法,通过wait休眠的线程,不会自动唤醒,需要依靠notify来唤醒
  2. sleep是线程类Thread提供的方法,休眠后到时间自动唤醒,不需要依靠其他方法

4.生产者消费者模式

​ 生产者将产品交给店员(Clerk),而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员叫生产者等一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品

生产者生产的商品保存在仓库中:

public class Factory {
	private int num = 1;// 商品数量,默认为10个

	/**
	 * 商品入库
	 */
	public synchronized void addProduct() {
		if (num >= 10) {
			// 这里不能继续生产了
			System.out.println("仓库已满,不能再生产了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			num++;
			System.out.println("生产者生产了一个商品,现在的商品库存为:" + num);
			this.notify();
		}
	}

	/**
	 * 商品出库
	 */
	public synchronized void subProduct() {
		if (num <= 0) {
			// 没有商品了,所以不能继续消费了
			System.out.println("商品没有了,不能继续消费了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			num--;
			System.out.println("消费者消费了一个商品,现在的商品库存为:" + num);
			this.notify();
		}
	}
}
 

生产者生产了商品,就需要把商品存放到仓库中:

public class Productor implements Runnable {
	private Factory factory;

	public Productor(Factory factory) {
		this.factory = factory;
	}

	@Override
	public void run() {
		while (true) {
			factory.addProduct();
		}
	}
}

消费者要想实现消费,也需要从仓库中获取商品:

public class Customer implements Runnable {
	private Factory factory;

	public Customer(Factory factory) {
		this.factory = factory;
	}

	@Override
	public void run() {
		while (true) {
			factory.subProduct();
		}
	}
}

测试代码:

/**
 * 生产者消费者模式
 * 生产者生产商品,消费者用来消费商品
 * 每生产一个商品,商品的数量就应该加1,没消费一个商品,商品的数量就要减1
 * 应该有一个地方用来保存商品,比如仓库
 * 仓库用来保存商品,保存时,商品数量应该有上限(比如数量不能超过10个)
 * 当仓库的商品数量达到10个以后,不能再生产了
 * 当商品数量为0以后,消费者就不能再消费了
 * 
 * 
 * @author wendi
 *
 */
public class Test {
	public static void main(String[] args) {
		Factory factory = new Factory();
		Productor p = new Productor(factory);
		Customer c = new Customer(factory);
		new Thread(p).start();
		new Thread(c).start();
	}
}

运行结果: 

生产者生产了一个商品,现在的商品库存为:2
生产者生产了一个商品,现在的商品库存为:3
生产者生产了一个商品,现在的商品库存为:4
生产者生产了一个商品,现在的商品库存为:5
生产者生产了一个商品,现在的商品库存为:6
生产者生产了一个商品,现在的商品库存为:7
生产者生产了一个商品,现在的商品库存为:8
消费者消费了一个商品,现在的商品库存为:7
生产者生产了一个商品,现在的商品库存为:8
消费者消费了一个商品,现在的商品库存为:7
消费者消费了一个商品,现在的商品库存为:6
消费者消费了一个商品,现在的商品库存为:5
消费者消费了一个商品,现在的商品库存为:4
消费者消费了一个商品,现在的商品库存为:3
消费者消费了一个商品,现在的商品库存为:2
生产者生产了一个商品,现在的商品库存为:3
生产者生产了一个商品,现在的商品库存为:4
生产者生产了一个商品,现在的商品库存为:5
生产者生产了一个商品,现在的商品库存为:6
生产者生产了一个商品,现在的商品库存为:7
生产者生产了一个商品,现在的商品库存为:8
生产者生产了一个商品,现在的商品库存为:9
生产者生产了一个商品,现在的商品库存为:10
仓库已满,不能再生产了
消费者消费了一个商品,现在的商品库存为:9
生产者生产了一个商品,现在的商品库存为:10
仓库已满,不能再生产了
消费者消费了一个商品,现在的商品库存为:9
消费者消费了一个商品,现在的商品库存为:8
消费者消费了一个商品,现在的商品库存为:7
消费者消费了一个商品,现在的商品库存为:6
消费者消费了一个商品,现在的商品库存为:5
消费者消费了一个商品,现在的商品库存为:4
消费者消费了一个商品,现在的商品库存为:3
生产者生产了一个商品,现在的商品库存为:4
生产者生产了一个商品,现在的商品库存为:5
生产者生产了一个商品,现在的商品库存为:6
消费者消费了一个商品,现在的商品库存为:5
生产者生产了一个商品,现在的商品库存为:6
生产者生产了一个商品,现在的商品库存为:7
生产者生产了一个商品,现在的商品库存为:8
生产者生产了一个商品,现在的商品库存为:9
生产者生产了一个商品,现在的商品库存为:10
消费者消费了一个商品,现在的商品库存为:9
消费者消费了一个商品,现在的商品库存为:8
消费者消费了一个商品,现在的商品库存为:7
消费者消费了一个商品,现在的商品库存为:6
消费者消费了一个商品,现在的商品库存为:5
消费者消费了一个商品,现在的商品库存为:4
消费者消费了一个商品,现在的商品库存为:3
消费者消费了一个商品,现在的商品库存为:2
消费者消费了一个商品,现在的商品库存为:1
消费者消费了一个商品,现在的商品库存为:0
商品没有了,不能继续消费了
生产者生产了一个商品,现在的商品库存为:1
生产者生产了一个商品,现在的商品库存为:2
生产者生产了一个商品,现在的商品库存为:3
生产者生产了一个商品,现在的商品库存为:4
消费者消费了一个商品,现在的商品库存为:3
消费者消费了一个商品,现在的商品库存为:2
消费者消费了一个商品,现在的商品库存为:1
消费者消费了一个商品,现在的商品库存为:0
生产者生产了一个商品,现在的商品库存为:1
消费者消费了一个商品,现在的商品库存为:0
。。。。。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值