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();

    }

}

 

你可能感兴趣的:(生产者消费者)