刚接触多线程 很多东西很晕,譬如网上这段代码,请教一下:其中有一段对这段代码的点评:“出现了重复读取的问题,也肯定有重复覆盖的问题”
1.请问为什么会这这样?
2.因为Info的set方法和get方法都加上了synchronized ,所以当又一个线程调用了其中的一个方法时候(比如set),另外一个方法(比如get)也就被这个线程占用,不能被别的线程占用,这样理解对不?3.不知道为什么会出现这样的运行结果,生产者线程不是已经占用Info的set和get ,然后在循环中一直把名字和年龄改来改去吗?消费者线程为什么还能输出每次生产者线程修改的结果?
这个程序的运行过程究竟是咋样的?谢谢前辈
class Info {
     
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public synchronized void set(String name, int age){
        this.name=name;
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        this.age=age;
    }
     
    public synchronized void get(){
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(this.getName()+"<===>"+this.getAge());
    }
    private String name = "Rollen";
    private int age = 20;
}
 
/**
 * 生产者
 * */
class Producer implements Runnable {
    private Info info = null;
 
    Producer(Info info) {
        this.info = info;
    }
 
    public void run() {
        boolean flag = false;
        for (int i = 0; i < 25; ++i) {
            if (flag) {
                 
                this.info.set("Rollen", 20);
                flag = false;
            } else {
                this.info.set("ChunGe", 100);
                flag = true;
            }
        }
    }
}
 
/**
 * 消费者类
 * */
class Consumer implements Runnable {
    private Info info = null;
 
    public Consumer(Info info) {
        this.info = info;
    }
 
    public void run() {
        for (int i = 0; i < 25; ++i) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            this.info.get();
        }
    }
}
 
/**
 * 测试类
 * */
public class hello {
    public static void main(String[] args) {
        Info info = new Info();
        Producer pro = new Producer(info);
        Consumer con = new Consumer(info);
        new Thread(pro).start();
        new Thread(con).start();
    }
}运行结果:
Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100

解决方案 »

  1.   

     for (int i = 0; i < 25; ++i) {
                if (flag) {
                      
                    this.info.set("Rollen", 20);
                    flag = false;
                } else {
                    this.info.set("ChunGe", 100);
                    flag = true;
                }
            }这段代码运行的太快了,瞬间就结束了,也就是说,他根本没有等消费者使用,就运行完毕了。你应该弄一个队列,或者堆栈,把生产的数据挨个放进去,消费者则挨个的获取。
    有个Queue的类适合这个
      

  2.   

    同楼上,按你的代码来看,估计要在
     for (int i = 0; i < 25; ++i) {
                 if (flag) {
                       
                     this.info.set("Rollen", 20);
                     flag = false;
                 } else {
                     this.info.set("ChunGe", 100);
                     flag = true;
                 }
             }
    里面加一个Thread.sleep(100)才能达到你的目的
      

  3.   

    提供一多线程例子
    public class Yi_Hong_Courtyard { public static void main(String[] args) {
    // TODO Auto-generated method stub
    Yi_Hong_Courtyard yunxing = new Yi_Hong_Courtyard(); }
    Yi_Hong_Courtyard(){

    Procuress procuress = new Procuress();

    Miss miss = new Miss(procuress);
    Piao_Guest guest = new Piao_Guest(procuress);

    Thread t_miss = new Thread(miss);
    Thread t_guest = new Thread(guest);

    Produce_Business();//内容介绍{函数在29--31行}

    t_miss.start();
    t_guest.start();

    }

    public void Produce_Business(){
    System.out.println("欢迎光临大日本怡红院-----祝您玩的愉快(xi wang nin zai e gao zhong xue hui duo xian cheng)");
    }
    }//小姐...给钱就干
    class Miss implements Runnable{ Procuress procuress;

    public Miss(Procuress procuress){
    this.procuress = procuress;
    }

    @Override
    public void run() {
    // TODO Auto-generated method stub
    int i = 1;
    while(true){
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }
    if(i == 1){
    try {
    procuress.fenpen_miss("苍井空","500日元");
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }else {
    try {
    procuress.fenpen_miss("甜心花子", "800日元");
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    i = (i+1) % 2;
    }
    }

    }//嫖客...花钱就嫖
    class Piao_Guest implements Runnable{ Procuress procuress;

    public Piao_Guest(Procuress procuress){
    this.procuress = procuress;
    }

    @Override
    public void run() {
    // TODO Auto-generated method stub
    while(true){
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }
    try {
    procuress.make_love();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }

    }//老鸨...统一管理小姐内部工作
    class Procuress{

    private String miss = null;
    private String price = null;
    private boolean jie_Guest = true;

    public synchronized void fenpen_miss(String miss,String price) throws InterruptedException{
    if(!jie_Guest)
    wait();//等待
    this.miss = miss;
    this.price = price;
    jie_Guest = false;
    notify();//叫醒
    }

    public synchronized void make_love() throws InterruptedException{
    if(jie_Guest)
    wait();//等待
    System.out.println("接客小姐:"+miss);
    System.out.println("接客价格:"+price);
    System.out.println("  "+"  "+"  "+"  "+"  "+"  "+"  "+"  "+"  "+"  "+miss+"工作完事"+"准备接客... ...");
    System.out.println("****************************************");
    jie_Guest = true;
    notify();//叫醒
    }
    }
      

  4.   


    加上了Thread.sleep(100)之后输出结果会有
    Rollen<===>20
    ChunGe<===>100
    间隔出现但为什么生产者线程占用了set和get方法后,消费者线程还能调用get方法,这两个方法不是被synchronized锁住了吗?
      

  5.   


    这里消费者为什么还能调用get方法?不是被生产者锁住了吗?
      

  6.   


     for (int i = 0; i < 25; ++i) {            if (flag) {                                  this.info.set("Rollen", 20);                flag = false;            } else {                this.info.set("ChunGe", 100);                flag = true;            }        }这个锁,只有你调用
    this.info.set("Rollen", 20);  
    和 this.info.set("ChunGe", 100);
    的时候会锁住,这两行执行完了,锁就放开了
    除非你是synchronized把整段括起来
      

  7.   

     为什么Info参数可以共用?
      

  8.   


    明白了 是在调用set方法时候才锁住,但是一调用完的时候,锁就释放了,另一个线程可以调用这个方法了!