Java Semaphore 生产者消费者线程同步

来源:互联网 发布:大数据自学书籍推荐 编辑:程序博客网 时间:2024/05/30 23:27

一说到Java线程同步,首先想到的就是synchronized关键字,用来锁对象。实际上在Java的java.util.concurrent包中就给我们提供了很多关于同步的工具类。这里为大家介绍Semaphore这个类。这个类是干嘛用的呢?就好比信号标识,它把这十个房间的信息都标识到一个电子信息站牌中,这个信息牌管理所有的房间信息,当有空余的房间时,所有需要放物品的线程都会知道,并抢房间的授权资格,当放抢到授权资格的线程放入物品后,所有需取物品的线程就进入放入物品和抢授权资格的过程。具体代码如下,这个例子,实现了多个线程同时往一个容器中放物品,如果这个容器中的物品数大于10的时候,所有放入线程处于等待状态;还实现了多个线程同时往容器中取物品,当容器中物品为空时,取物线程等待。简单一句话描述:在不冲突的过程中从容器中多放,多取。

package thread.semaphore.two;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;public class SemaphoreTest {    public static void main(String[] args) {        // 线程执行器        ExecutorService executor = Executors.newCachedThreadPool();        // 产生仓库        Warehouse warehouse = new Warehouse();        // 设置限额信号        Semaphore notFull = new Semaphore(10);        // 设置非空信号        Semaphore notEmpty = new Semaphore(0);        // 产生生产者        PutterRunnable putter1 = new PutterRunnable(warehouse, "put1", notFull, notEmpty);        PutterRunnable putter2 = new PutterRunnable(warehouse, "put2", notFull, notEmpty);        // 产生消费者        GetterRunnable getter1 = new GetterRunnable(warehouse, "get1", notFull, notEmpty);        GetterRunnable getter2 = new GetterRunnable(warehouse, "get2", notFull, notEmpty);        executor.execute(putter1);        executor.execute(putter2);        executor.execute(getter1);        // 如果有需要,可以把这个方法放开,就可以实现多放多取。        // executor.execute(getter2);    }    // 数据存储仓库    static class Warehouse {        // 库存容量        List<Object> list = new ArrayList<Object>();        // 核心锁(非冲突锁)        Semaphore core = new Semaphore(1, true);        public void put(Object obj, String threadName) {            try {                // 保证不冲突                core.acquire();                list.add(obj);                // 判断在生产时,填充位的对象是否是已经有值的,如果有则表示程序错误                System.out.println("+++ " + threadName + "  list.size = " + list.size() + ";放入的obj=" + obj);                // 退出核心锁                core.release();            } catch (Exception e) {                e.printStackTrace();            } finally {            }        }        @SuppressWarnings("finally")        public Object get(String threadName) {            Object obj = null;            try {                // 保证不冲突                core.acquire();                obj = list.remove(0);                // 判断在消费时,需要消费位置的对象是否是空的。,如果有则表示程序错误                System.out.println("            --- " + threadName + "  list.size = " + list.size() + ";取出的obj=" + obj);                // 退出核心锁                core.release();            } catch (Exception e) {                e.printStackTrace();            } finally {                return obj;            }        }    }    // putter线程,    static class PutterRunnable implements Runnable {        Warehouse warehouse;        Random random;        String rannableName;        // 非满锁        Semaphore notFull;        // 非空锁        Semaphore notEmpty;        public PutterRunnable(Warehouse warehouse, String rannableName, Semaphore notFull, Semaphore notEmpty) {            this.warehouse = warehouse;            random = new Random();            this.rannableName = rannableName;            this.notFull = notFull;            this.notEmpty = notEmpty;        }        @Override        public void run() {            while (true) {                try {                    // 获取存储限额的插入许可,如果达到限额,则等待插入许可,否则继续往下执行                    notFull.acquire();                    warehouse.put((Object) (random.nextInt() + ""), rannableName);                    // 插入成功后,则添加非空的授权许可。以供获取线程获取                    notEmpty.release();                    // TimeUnit.SECONDS.sleep(1);                } catch (Exception e) {                    e.printStackTrace();                }            }        }    }    static class GetterRunnable implements Runnable {        Warehouse warehouse;        String rannableName;        // 非空锁,当是0的时候进行阻塞        Semaphore notEmpty;        // 非满锁        Semaphore notFull;        public GetterRunnable(Warehouse warehouse, String rannableName, Semaphore notFull, Semaphore notEmpty) {            this.warehouse = warehouse;            this.rannableName = rannableName;            this.notFull = notFull;            this.notEmpty = notEmpty;        }        @Override        public void run() {            while (true) {                try {                    // 获取非空授权许可,如果为空,则一直阻塞,等待插入线程插入后添加非空许可                    notEmpty.acquire();                    warehouse.get(rannableName);                    // 添加存储限额的插入许可,表示插入线程可以进行添加操作了                    notFull.release();                    TimeUnit.SECONDS.sleep(1);                } catch (Exception e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    }}

执行结果如下:

<div>+++ put1  list.size = 1;放入的obj=-2139723420+++ put2  list.size = 2;放入的obj=-1572405971+++ put1  list.size = 3;放入的obj=-1705274050            --- get1  list.size = 2;取出的obj=-2139723420+++ put2  list.size = 3;放入的obj=734422456+++ put1  list.size = 4;放入的obj=-1619127788+++ put2  list.size = 5;放入的obj=-1719033923+++ put1  list.size = 6;放入的obj=-122350698+++ put2  list.size = 7;放入的obj=2035853367+++ put1  list.size = 8;放入的obj=-538022868+++ put2  list.size = 9;放入的obj=-1842381319+++ put1  list.size = 10;放入的obj=-1810284972            --- get1  list.size = 9;取出的obj=-1572405971+++ put2  list.size = 10;放入的obj=-555471275            --- get1  list.size = 9;取出的obj=-1705274050+++ put1  list.size = 10;放入的obj=-1173490502            --- get1  list.size = 9;取出的obj=734422456+++ put2  list.size = 10;放入的obj=-313790792            --- get1  list.size = 9;取出的obj=-1619127788+++ put1  list.size = 10;放入的obj=-1067498081            --- get1  list.size = 9;取出的obj=-1719033923+++ put2  list.size = 10;放入的obj=-1634780208            --- get1  list.size = 9;取出的obj=-122350698+++ put1  list.size = 10;放入的obj=-1420550696            --- get1  list.size = 9;取出的obj=2035853367+++ put2  list.size = 10;放入的obj=2036388541            --- get1  list.size = 9;取出的obj=-538022868+++ put1  list.size = 10;放入的obj=-320507030            --- get1  list.size = 9;取出的obj=-1842381319+++ put2  list.size = 10;放入的obj=1682783427            --- get1  list.size = 9;取出的obj=-1810284972+++ put1  list.size = 10;放入的obj=243200254<div>


0 0
原创粉丝点击