资源存入与取出的并发问题
将图用代码进行无并发描述
package com.javaxl.thread; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-05-29 21:34 * <p> * 操作同一个资源 * 资源中只有姓名和性别 * 生产者对应一个生产的线程 * 消费者对应一个消费的线程 */ public class Demo4 { public static void main(String[] args) { // 一个资源池 Res r = new Res(); Thread in = new Thread(new Input(r)); Thread out = new Thread(new Output(r)); in.start(); out.start(); } } class Res { String name; String sex; boolean flag = true; public Res(String name, String sex) { this.name = name; this.sex = sex; } public Res() { } } /** * 往资源池中生产 */ class Input implements Runnable { private Res r; private int num = 0; public Input(Res r) { this.r = r; } @Override public void run() { while (true) { synchronized (r) { if (num % 2 == 0) { r.name = "tingting"; r.sex = "nv"; } else { r.name = "旺旺"; r.sex = "男"; } num++; } } } } /** * 从资源池消费 */ class Output implements Runnable { private Res r; public Output(Res r) { this.r = r; } @Override public void run() { while (true) { synchronized (r) { System.out.println(r.name + "--------------" + r.sex); } } } }
控制台结果
加上同步锁出现的问题
上面代码保证了资源获取的一致性。
现有问题:
需求是往资源池中放入一个资源,然后再从资源池中取一个资源;
但是现在情况是,存入N个资源,在不定数量的取N个资源;
并且注意一点:目前向资源池中存放资源的只有一个线程,从资源池中消费资源的也只有一个线程。
Wait():
Notify():
notifyAll():
都是用在同步中,因为要对持有监听器(锁)的线程操作;
所以要使用在同步中,因为只有同步才具有锁;
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识他们所操作线程持有的锁;
只有同一个锁上的被等待线程,可以被同一个锁上notify()唤醒;
不可以对不同锁中的线程进行唤醒;
也就是说,等待和唤醒必须是同一把锁;
而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中;
改进前面生产者消费者产生的问题
package com.javaxl.thread; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-05-29 21:34 * <p> * 操作同一个资源 * 资源中只有姓名和性别 * 生产者对应一个生产的线程 * 消费者对应一个消费的线程 */ public class Demo4 { public static void main(String[] args) { // 一个资源池 Res r = new Res(); Thread in = new Thread(new Input(r)); Thread out = new Thread(new Output(r)); in.start(); out.start(); } } class Res { String name; String sex; boolean flag = false; public Res(String name, String sex) { this.name = name; this.sex = sex; } public Res() { } } /** * 往资源池中生产 */ class Input implements Runnable { private Res r; private int num = 0; public Input(Res r) { this.r = r; } @Override public void run() { while (true) { synchronized (r) { if (r.flag){ try { r.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (num % 2 == 0) { r.name = "tingting"; r.sex = "nv"; } else { r.name = "旺旺"; r.sex = "男"; } num++; r.flag = true; r.notify(); } } } } /** * 从资源池消费 */ class Output implements Runnable { private Res r; public Output(Res r) { this.r = r; } @Override public void run() { while (true) { synchronized (r) { if(!r.flag){ try { r.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(r.name + "--------------" + r.sex); r.flag = false; r.notify(); } } } }
上面代码保证了,在只有一个生产者、一个消费者的情况下,资源池的资源呈现出反复一进一出的现象;
代码优化(成员私有化)
package com.javaxl.thread; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-05-29 21:34 * <p> * 操作同一个资源 * 资源中只有姓名和性别 * 生产者对应一个生产的线程 * 消费者对应一个消费的线程 */ public class Demo4 { public static void main(String[] args) { // 一个资源池 Res r = new Res(); Thread in = new Thread(new Input(r)); Thread out = new Thread(new Output(r)); in.start(); out.start(); // Thread in2 = new Thread(new Input(r)); // Thread out2 = new Thread(new Output(r)); // in2.start(); // out2.start(); } } class Res { private String name; private String sex; private boolean flag = false; private int num = 0; public Res(String name, String sex) { this.name = name; this.sex = sex; } public Res() { } /** * 往资源池中添加资源 */ public synchronized void add(){ if (this.flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (num % 2 == 0) { this.name = "tingting"; this.sex = "nv"; } else { this.name = "旺旺"; this.sex = "男"; } num++; this.flag = true; this.notify(); } /** * 使用资源池中的资源 */ public synchronized void use(){ if(!this.flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(this.name + "--------------" + this.sex); this.flag = false; this.notify(); } } /** * 往资源池中生产 */ class Input implements Runnable { private Res r; public Input(Res r) { this.r = r; } @Override public void run() { while (true) { r.add(); } } } /** * 从资源池消费 */ class Output implements Runnable { private Res r; public Output(Res r) { this.r = r; } @Override public void run() { while (true) { r.use(); } } }
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有