• java多线程1-生产者与消费者


    1.5之前的写法.

    /*
    生产者消费者
    两个线程生产,两个线程消费.
    而且要是生产一个消费一个.
    
    主要问题:使用notifyAll会唤醒本方线程,这个问题要lock和conditions来处理.
    如果不用notifyAll,只用notify所有线程都会wait.
    */
    class  TestMain
    {
        public static void main(String[] args) 
        {
            Resource res = new Resource();
            Producer pro = new Producer(res);
            Consumer con = new Consumer(res);
            Thread t1 = new Thread(res);
            Thread t2 = new Thread(pro);
            Thread t3 = new Thread(res);
            Thread t4 = new Thread(pro);
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    class Resource
    {
        private String name;
        private int count=1;
        private boolean flag =false;
    
        public synchronized void set(String name){
            if(flag){
                try{
                    wait();//线程会停在这里,但是当线程被唤醒的时候,一样要循环判断标记.所以if要改成while
                }catch(Exception e){
                    //如果出异常,方法结束,就出了synchronized代码块锁也有释放了.这点不像lock.nulock().nulock是一定要执行的,出了异常,方法结束也是要执行的.
                }
            }            
            this.name=name+"--"+count++;
            System.out.println(Thread.curentThread().getName()+"生产的"+this.name);
            flag=true;
            this.notify();//这里唤醒的时候可能唤醒的是本方线程,导致所有线程wait,所以要用 notifyAll()
        }
        public synchronized void out(){
            if(!flag){
                try{
                    wait();
                }catch(Exception e){
                    //
                }
            }
            System.out.println(Thread.curentThread().getName()+"消费者"+this.name);
            flag=false;
            this.notify();
        }
    }
    class Producer implements Runnable
    {
        private Resource res;
        Producer(Resource res){
            this.res=res;
        }
        @Override
        public void run(){
            while(true){
                res.set("+商品+");
            }
        }
    }
    
    class Consumer implements Runnable
    {
        private Resource res;
        Producer(Resource res){
            this.res=res;
        }
        @Override
        public void run(){
            while(true){
                res.out();
            }
        }
    }

    1.5之后的写法

    /*
    生产与消费者
    jdk1.5 之后的Lock与Condition
    可以保证唤醒的是对方线程,可以唤醒对方一个,也可以是所有.主要看用的是signal与signalAll()
    
    */
    class  TestMain
    {
        public static void main(String[] args) 
        {
            //要操作的数据,资源
            Resource res = new Resource();
            //两个生产,消费线程
            Producer pro = new Producer(res);
            Resource res = new Resource();
            Producer pro = new Producer(res);
            Consumer con = new Consumer(res);
            Thread t1 = new Thread(res);
            Thread t2 = new Thread(pro);
            Thread t3 = new Thread(res);
            Thread t4 = new Thread(pro);
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    }
    /*
      资源类,里面的要操作的数据,操作数据的方法,标记,锁,Condition.
    */
    class Resource
    {
        private String name;
        private int count=1;
        private boolean flag =false;
        
        //1.5之后lock代替了,syschronized
        private Lock lock =new ReentrantLock();
        //Condition 代替了Objcet里面的wait,notify,notifyAll
        private Condition condition1=lock.newCondition();
        
        //用来分组线程,本方只唤醒对方线程的操作.
        private Condition condition2=lock.newCodition();
    
        //去掉了synchronized关键字
        public void set(String name){
    
            while(flag){
                try{
                    condition1.await();
                }catch(Exception e){
                    //这里一但出异常,因为还没有执行lock.unlock()会,所以方法结束但是锁还没有释放,所以一定要入finally里面去执行nulock();
                }
            }            
            this.name=name+"--"+count++;
            System.out.println(Thread.curentThread().getName()+"生产的"+this.name);
            flag=true;
            //condition.signalAll();//这样可能会唤醒本方线程.用signal()会全部等待.
    
            condition2.signal()//这样可以保证唤醒的是对方线程.
            lock.unlock();
        }
        //去掉synchronized
        public  void out(){
            lock.loct();
            try{
                while(!flag){
                    condition2.await()//线程被唤醒后,一定要循环判断标记
                }
                System.out.println(Thread.curentThread().getName()+"消费者"+this.name);
                flag=false;
                //condition.signalAll();//这里同样可能会唤醒本方的线程,要改的
                condition2.signa();
            }catch(InterrputedException e){
                //await()的时候可会出异常,出了异常方法结束了,但也定要nulock()
            }finally{
                lock.nulock();
            }
        }
    }
    /*
    生产者线程
    */
    class Producer implements Runnable
    {
        private Resource res;
        Producer(Resource res){
            this.res=res;
        }
        @Override
        public void run(){
            while(true){
                res.set("+商品+");
            }
        }
    }
    /*
    消费者线程
    */
    class Consumer implements Runnable
    {
        private Resource res;
        Producer(Resource res){
            this.res=res;
        }
        @Override
        public void run(){
            while(true){
                res.out();
            }
        }
    }
  • 相关阅读:
    谷歌浏览器本地调试时调用服务跨域
    SVN提交时忽略不必提交的文件夹和文件,如node_modules
    热点链接实现不规则菜单
    easyui分页控件的应用
    Filter过滤器的应用
    SVG绘图学习总结
    VS2010无法调试页面问题
    java学习
    webservice配置
    jQuery
  • 原文地址:https://www.cnblogs.com/yinyu/p/5313491.html
Copyright © 2020-2023  润新知