一 体系化深入学习并发编程由简入繁系统梳理并发知识点( 七 )


每次运行,三个线程的顺序都有可能不相同,因为唤醒线程将它们同时唤醒,所以它们会同时再次竞争,谁先竞争到锁,谁就先执行 。
值得注意的是状态的变化:
本来执行wait时进入了等待的情况,但是由于被唤醒后竞争锁失败,就直接从或者Timed 状态进入状态
同样,如果在等待中发生了异常,也没有进入到状态,就直接跳转到了状态
使用wait和实现生产者消费者模式
先建立一个仓库类:
class TransactionStorage{private int maxszie;private LinkedList list;//设置仓库容量public TransactionStorage(int maxszie) {this.list = new LinkedList<>();this.maxszie=maxszie;}public synchronized void put() throws InterruptedException {if (list.size()==maxszie){//库存满了就等待wait();}list.add(new Date());System.out.println("生产者生产了商品,仓库剩余容量"+list.size());//仓库有库存就唤醒消费者notify();}public synchronized void take() throws InterruptedException {if (list.size()==0){//仓库没有库存就进入等待wait();}System.out.println(list.poll()+"消费者购买了商品,仓库剩余容量:"+list.size());//仓库有空位就唤醒生产者notify();}}
生产者类:
class Producer implements Runnable{TransactionStorage storage;public Producer(TransactionStorage storage) {this.storage = storage;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {try {//将产品放入仓库storage.put();} catch (InterruptedException e) {e.printStackTrace();}}}}
消费者类:
class Consumer implements Runnable{TransactionStorage storage;public Consumer(TransactionStorage storage) {this.storage = storage;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {try {//从仓库取出产品storage.take();} catch (InterruptedException e) {e.printStackTrace();}}}}
主类:
public class ProducerConsumerModel {public static void main(String[] args) {TransactionStorage storage = new TransactionStorage(10);Thread producer = new Thread(new Producer(storage));Thread consumer = new Thread(new Consumer(storage));producer.start();consumer.start();}}
.sleep() sleep的特点
下面是该方法的官方文档介绍
theto sleep ( cease ) for theof ,to theandofand . Thedoes not loseof any .
sleep()方法可以使当前线程休息一端时间,而不占用CPU资源
不过比较特殊的是,它和wait方法不一样,它不会释放锁
无论是还是lock
即在休眠时,该线程仍然持有锁,休眠完后,继续执行
public static void main(String[] args) {Runnable r = new Runnable() {@Overridepublic void run() {synchronized (this){System.out.println(Thread.currentThread().getName()+"获取到了monitor");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"退出同步代码块");}}};new Thread(r).start();new Thread(r).start();}
public static void main(String[] args) {ReentrantLock lock = new ReentrantLock();Runnable r = () -> {try {lock.lock();System.out.println(Thread.currentThread().getName()+"获取到了lock");Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}finally {lock.unlock();System.out.println(Thread.currentThread().getName()+"释放了lock");}};new Thread(r).start();new Thread(r).start();}
sleep响应中断
当sleep感受到中断时,会抛出,并且清除中断状态,这一点我们在之前停止线程时已经提到过了,下面是推荐一个更好用的sleep方法