• 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();
        }
    }
  • 相关阅读:
    剑指offer-序列化二叉树
    剑指offer-把字符串转换成整数
    CentOS终端账户切换
    bootstrap3 modal居中
    海洋地理信息系统的应用现状及其发展趋势
    智慧城市八大应用,助力城市更加智慧
    zTree触发节点click,check事件
    Linux Centos下软件的安装与卸载方法
    MongoDB系列教程大全
    openlayers加载切片错位解决方案
  • 原文地址:https://www.cnblogs.com/luogankun/p/3991363.html
Copyright © 2020-2023  润新知