首页 > 代码库 > jdk线程的生产者消费者问题

jdk线程的生产者消费者问题

同步代码块实现生产者消费者模式

class Person {    private String name;    private String sex;    private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空    //生产    public void set(String name, String sex) {        synchronized (this) {            // if(isEmpty)            while (!isEmpty.equals(Boolean.TRUE)) {                // 区域不为空,此时生产者应该停下来,等着消费者消费                try {this.wait();// 等待 消费者消费} catch (InterruptedException e) {}            }            this.name = name;            try {Thread.sleep(1); } catch (InterruptedException e) {e.printStackTrace();}            this.sex = sex;            // 生产者生产之后,应该修改存储区域的状态            isEmpty = Boolean.FALSE;// 不为空            this.notifyAll();// 唤醒消费者,起来吃东西了        }    }    //消费    public void get() {        synchronized (this) {            // 存储区域为空            while (!isEmpty.equals(Boolean.FALSE)) {                try {this.wait();// 等着生产者去生产} catch (InterruptedException e) {}            }            String name = getName();            String sex = getSex();            System.out.println(name + " --> " + sex);            // 消费完成,应该修改存储区域的状态            isEmpty = Boolean.TRUE;// 空了            this.notifyAll();// 唤醒生产者,        }    }     getter/setter}//生产者class Producer implements Runnable {    private Person p;    public Producer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            if (i % 2 == 0) {                p.set("春哥哥", "男");            } else {                p.set("著姐", "女");            }        }    }}//消费者class Consumer implements Runnable {    private Person p;    public Consumer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            p.get();        }    }}public class Producer_ConsumerDemo {    public static void main(String[] args) {        Person p = new Person();        new Thread(new Producer(p)).start();        new Thread(new Consumer(p)).start();        new Thread(new Producer(p)).start();        new Thread(new Consumer(p)).start();    }}

 

同步方法实现生产者消费者模式

class Person {    private String name;    private String sex;    private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空    //生产    public synchronized void set(String name, String sex) {        // if(isEmpty)        while (!isEmpty.equals(Boolean.TRUE)) {            // 区域不为空,此时生产者应该停下来,等着消费者消费            try {this.wait();// 等待 消费者消费} catch (InterruptedException e) {}        }        this.name = name;        try {Thread.sleep(1); } catch (InterruptedException e) {}        this.sex = sex;        // 生产者生产之后,应该修改存储区域的状态        isEmpty = Boolean.FALSE;// 不为空        this.notifyAll();// 唤醒消费者,起来吃东西了    }    //消费    public synchronized void get() {        // 存储区域为空        while (!isEmpty.equals(Boolean.FALSE)) {            try {this.wait();// 等着生产者去生产} catch (InterruptedException e) {}        }        String name = getName();        String sex = getSex();        System.out.println(name + " --> " + sex);        // 消费完成,应该修改存储区域的状态        isEmpty = Boolean.TRUE;// 空了        this.notifyAll();// 唤醒生产者,    }    getter/setter}//生产者class Producer implements Runnable {    private Person p;    public Producer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            if (i % 2 == 0) {                p.set("春哥哥", "男");            } else {                p.set("著姐", "女");            }        }    }}class Consumer implements Runnable {    private Person p;    public Consumer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            p.get();        }    }}public class Producer_ConsumerDemo {    public static void main(String[] args) {        Person p = new Person();        new Thread(new Producer(p)).start();        new Thread(new Consumer(p)).start();        new Thread(new Producer(p)).start();        new Thread(new Consumer(p)).start();    }}

 

可重入锁实现生产者消费者模式

jkd1.5后的另一种同步机制:通过显示定义同步锁对象来实现同步,这种机制,同步锁应该使用Lock对象充当;

在实现线程安全控制中,通常使用ReentrantLock(可重入锁)。使用该对象可以显示地加锁和解锁

具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

格式:

public class X {    private final ReentrantLock lock = new ReentrantLock();    //定义需要保证线程安全的方法    public void  m(){        lock.lock();//加锁        try{            //... method body        }finally{            lock.unlock();//在finally释放锁        }    }}

可重入锁没有同步监听对象,咋办呢?

Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用

class Person {    private final ReentrantLock lock = new ReentrantLock();// 创建可重入锁对象        private  final  Condition con = lock.newCondition();    private String name;    private String sex;    private Boolean isEmpty = Boolean.TRUE; // 表示存储区域是否为空    //生产    public void set(String name, String sex) {        lock.lock();        while(!isEmpty.equals(Boolean.TRUE)){ //表示不空状态            try {con.await();} catch (InterruptedException e) {}}        try {            this.name = name;            Thread.sleep(1);            this.sex = sex;            isEmpty = Boolean.FALSE;            con.signal();        } catch (InterruptedException e) {} finally {            lock.unlock();        }    }    //消费    public void get() {        lock.lock();        while(!isEmpty.equals(Boolean.FALSE)){ //存储区域为空,消费者应该等着            try {                con.await();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        try {            String name = getName();            String sex = getSex();            System.out.println(name + " --> " + sex);            //            isEmpty = Boolean.TRUE;            con.signal();        } finally {            lock.unlock();        }            }    getter/setter}//生产者class Producer implements Runnable {    private Person p;    public Producer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            if (i % 2 == 0) {                p.set("春哥哥", "男");            } else {                p.set("著姐", "女");            }        }    }}class Consumer implements Runnable {    private Person p;    public Consumer(Person p) {        this.p = p;    }    public void run() {        for (int i = 0; i < 100; i++) {            p.get();        }    }}public class Producer_ConsumerDemo {    public static void main(String[] args) {        Person p = new Person();        new Thread(new Producer(p)).start();        new Thread(new Consumer(p)).start();    }}

 

同步代码块方式改写卖票程序

class MyRunnable implements Runnable {    private Integer num = 50;    public void run() {        for (int i = 0; i < 200; i++) {            sale();        }    }    private Object o = new Object();    public void sale() {        // synchronized (this) {        // synchronized (MyRunnable.class) {        synchronized (o) {            if (num > 0) {                try {Thread.sleep(1); } catch (InterruptedException e) {}                System.out.println(Thread.currentThread().getName() + "卖出第"                        + num-- + "张");            }        }    }}public class TicketDemoSyncByBlock {    public static void main(String[] args) {        Runnable target = new MyRunnable();        new Thread(target, "A").start();        new Thread(target, "B").start();        new Thread(target, "C").start();    }}

实现Runnable接口的方式,使用同步代码块的方式进行同步。

可以取的同步监听对象为:this、当前方法所在类的Class对象、任一不变对象

 

同步方法方式改写卖票程序

class MyRunnable implements Runnable {    private Integer num = 50;    public void run() {        for (int i = 0; i < 200; i++) {            sale();        }    }    synchronized public  void  sale() {        if (num > 0) {            try {                Thread.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "卖出第" + num--  + "张");        }    }}public class TicketDemoSyncByMethod {    public static void main(String[] args) {        Runnable target = new MyRunnable();        new Thread(target, "A").start();        new Thread(target, "B").start();        new Thread(target, "C").start();    }}

 

可重入锁方式改写卖票程序

class MyRunnable implements Runnable {    private final ReentrantLock lock = new ReentrantLock();    private Integer num = 50;    public void run() {        for (int i = 0; i < 200; i++) {            sale();        }    }    public void sale() {        lock.lock();        try {            if (num > 0) {                try {                    Thread.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println(Thread.currentThread().getName() + "卖出第"                        + num-- + "张");            }        } finally {            lock.unlock();        }    }}public class TicketDemoSyncByReentrantLock {    public static void main(String[] args) {        Runnable target = new MyRunnable();        new Thread(target, "A").start();        new Thread(target, "B").start();        new Thread(target, "C").start();    }}

 

jdk线程的生产者消费者问题