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();
    }
}
原文地址:https://www.cnblogs.com/luogankun/p/3991363.html