zoukankan      html  css  js  c++  java
  • 多线程操作

    题目:

    * 题目:现在两个线程,可以操作初始值为零的一个变量,
    * 实现一个线程对该变量加1,一个线程对该变量减1,
    * 实现交替,来10轮,变量初始值为零。

    看代码:

    package com.cxy.juc;
    
    
    class AirCondition{
        private int num = 0;
        public synchronized void increment() throws Exception{
            if(num !=0){
                this.wait();
            }
            num++;
            System.out.println(Thread.currentThread().getName()+"	"+num);
            this.notifyAll();
        }
        public synchronized void decrement() throws Exception{
            if (num ==0){
                this.wait();
            }
            num--;
            System.out.println(Thread.currentThread().getName()+"	"+num);
            this.notifyAll();
        }
    }
    
    /**
     * 多线程操作:  线程操作资源类,
     * 判断,干活,通知
     * 防止虚假唤醒
     */
    public class ProdConsumerDemo {
        public static void main(String[] args) throws Exception{
            AirCondition airCondition =new AirCondition();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"a").start();
    
            /*new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"c").start();*/
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"b").start();
    
           /* new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"d").start();*/
        }
    
    }

    执行结果是对的,

    a    1
    b    0
    a    1
    b    0
    a    1
    b    0
    a    1
    b    0
    a    1
    b    0
    a    1

    那么线程再增多呢,变成两个线程增加两个线程减少呢:

    package com.cxy.juc;
    
    
    class AirCondition{
        private int num = 0;
        public synchronized void increment() throws Exception{
            if(num !=0){
                this.wait();
            }
            num++;
            System.out.println(Thread.currentThread().getName()+"	"+num);
            this.notifyAll();
        }
        public synchronized void decrement() throws Exception{
            if (num ==0){
                this.wait();
            }
            num--;
            System.out.println(Thread.currentThread().getName()+"	"+num);
            this.notifyAll();
        }
    }
    
    /**
     * 多线程操作:  线程操作资源类,
     * 判断,干活,通知
     * 防止虚假唤醒
     */
    public class ProdConsumerDemo {
        public static void main(String[] args) throws Exception{
            AirCondition airCondition =new AirCondition();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"a").start();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"c").start();
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"b").start();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"d").start();
        }
    
    }

    看结果:

    b    0
    c    1
    d    0
    a    1
    d    0
    c    1
    b    0
    d    -1
    d    -2
    a    -1
    b    -2
    b    -3
    a    -2

    那么出现bug了,而且是api级别的bug,怎么办呢,

    多线程操作:高内聚低耦合,线程操作资源类,判断,干活,通知,防止虚假唤醒

    那么在那个里面就需要在判断的时候,虚假唤醒了;

    public final void wait()
                    throws InterruptedException导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。 换句话说,这个方法的行为就好像简单地执行呼叫wait(0) 。 
    当前的线程必须拥有该对象的显示器。 该线程释放此监视器的所有权,并等待另一个线程通知等待该对象监视器的线程通过调用notify方法或notifyAll方法notifyAll 。 然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。 
    
    像在一个参数版本中,中断和虚假唤醒是可能的,并且该方法应该始终在循环中使用: 
    
      synchronized (obj) {
             while (<condition does not hold>)
                 obj.wait();
             ... // Perform action appropriate to condition
         } 该方法只能由作为该对象的监视器的所有者的线程调用。 有关线程可以成为监视器所有者的方式的说明,请参阅notify方法。 
    异常 
    IllegalMonitorStateException - 如果当前线程不是对象监视器的所有者。 
    InterruptedException - 如果任何线程在当前线程等待通知之前或当前线程中断当前线程。 当抛出此异常时,当前线程的中断状态将被清除。 
    另请参见: 
    notify() , notifyAll() 

    所以需要将if判断变成while判断:

    a    1
    b    0
    c    1
    d    0
    a    1
    b    0
    c    1
    d    0
    a    1
    b    0
    c    1
    d    0
    a    1
    d    0
    c    1
    d    0

    结果就对了

    采用java的

    package com.cxy.juc;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    class Aicondition{
        private int num =0;
        private Lock lock =new ReentrantLock();
        private Condition condition=lock.newCondition();
        public  void increment() throws Exception{
            lock.lock();
            try {
                if (num !=0){
                    condition.await();
                }
                num++;
                System.out.println(Thread.currentThread().getName()+"	"+num);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
        public  void decrement() throws Exception{
            lock.lock();
            try {
                if (num !=0){
                    condition.await();
                }
                num--;
                System.out.println(Thread.currentThread().getName()+"	"+num);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
    }
    public class ProdConsumerDemo8 {
        public static void main(String[] args) {
            AirCondition airCondition =new AirCondition();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"a").start();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"c").start();
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"b").start();
    
            new Thread(() ->{
                for (int i = 0; i <10 ; i++) {
                    try {
                        airCondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"d").start();
        }
    }
  • 相关阅读:
    ==和equals
    Fastjson toJSONString 碰到的一个问题
    Java之旅之第一个Java项目[Sping+ Spring MVC + MyBatis] 项目框架
    Java之旅之第一个Java项目[Sping+ Spring MVC + MyBatis] 项目配置
    Java之旅之第一个Java项目[Sping+ Spring MVC + MyBatis] org.springframework.web相关源码
    Java之旅之第一个Java项目[Sping+ Spring MVC + MyBatis] 项目背景
    centos6 yum源不可用问题解决
    ORACLE修改最大连接数
    Docker学习笔记(二):Docker镜像
    Mysql5.7慢日志时间与系统时间相差8小时问题的解决
  • 原文地址:https://www.cnblogs.com/xiufengchen/p/11665406.html
Copyright © 2011-2022 走看看