2 sinat 34458693 sinat_34458693 于 2016.03.29 15:10 提问

java se 多线程资源共享问题
class bread{
    int num = 0;

    public synchronized void makeBreand(){
            num++;
            this.notify();      

    }

    public synchronized void sale(){
        while(num==0){
            try{
                this.wait();
                System.out.println("暂时无面包,等待");
            }catch(InterruptedException e){e.printStackTrace();}

        }
        num--;

    }
}

class makeThread implements Runnable{
bread account;

public makeThread(bread s){
    account = s;

}
public void run(){
while(account.num<10){
    account.makeBreand();
    System.out.println(Thread.currentThread().getName()+"thread is working");
    System.out.println("面包数量+1,已有"+account.num+"个面包");
    try{
        Thread.sleep(1000);
    }catch(InterruptedException e){e.printStackTrace();}
}
    }

}

class saleThread implements Runnable{
bread left;
public saleThread(bread s){
left = s;
}
public void run(){
if(left.num>0){
left.sale();
System.out.println(Thread.currentThread().getName()+"售出面包一个");
System.out.println("目前有"+left.num+"个面包");
try{
Thread.sleep(1000);
}catch(InterruptedException e){e.printStackTrace();}
}
}
}

public class test{
public static void main(String[] args){
bread b = new bread();

    saleThread sale = new saleThread(b);
    makeThread make = new makeThread(b);
    Thread t1 = new Thread(make);
    Thread t2 = new Thread(sale);
    t1.start();
    t2.start();
}

}

代码如下,运行效果:
Thread-1售出面包一个
Thread-0thread is working
目前有0个面包
面包数量+1,已有0个面包
Thread-0thread is working
面包数量+1,已有1个面包
Thread-0thread is working
面包数量+1,已有2个面包
Thread-0thread is working
面包数量+1,已有3个面包
Thread-0thread is working
面包数量+1,已有4个面包
Thread-0thread is working
面包数量+1,已有5个面包
Thread-0thread is working
面包数量+1,已有6个面包
Thread-0thread is working
面包数量+1,已有7个面包
Thread-0thread is working
面包数量+1,已有8个面包
Thread-0thread is working
面包数量+1,已有9个面包
Thread-0thread is working
面包数量+1,已有10个面包

为什么我的sale进程只被调用了一次?

4个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.29 15:45
已采纳

首先,sale操作是在线程1中执行的,因为第一个线程t1 先启动了,导致num很快就非0类,那么sale操作的while循环就结束了。
其次,你的一个操作中的打印语句应该放在同一条,因为是多线程环境下,比如你的sale操作中前后两条打印语句可能就是错乱的,不是同时出现的。修正下你的打印语句,就知道为什么了。

 class bread {
    int num = 0;

    public synchronized void makeBreand() {
        num++;
        this.notify();

    }

    public synchronized void sale() {
        System.out.println(Thread.currentThread().getName()+" num:"+num);
        while (num == 0) {
            try {
                System.out.println("暂时无面包,等待");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        num--;

    }
}

class makeThread implements Runnable {
    bread account;

    public makeThread(bread s) {
        account = s;

    }

    public void run() {
        while (account.num < 10) {
            account.makeBreand();
            System.out.println(Thread.currentThread().getName() + "thread is working"+"面包数量+1,已有" + account.num + "个面包");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class saleThread implements Runnable {
    bread left;

    public saleThread(bread s) {
        left = s;
    }

    public void run() {
        if (left.num > 0) {
            left.sale();
            System.out.println(Thread.currentThread().getName() + "售出面包一个"+"目前有" + left.num + "个面包");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
wojiushiwo945you
wojiushiwo945you 回复sinat_34458693: 你的saleThread类的run方法是用的是if而不是while,所以只会执行一次。如果要实现交替显示的效果,改成while循环判断才行。
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you 回复sinat_34458693: 你要显示什么效果呢?
2 年多之前 回复
sinat_34458693
sinat_34458693 回复毕小宝: 那请问,我该如何修改才能达到我要的效果?
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you 回复sinat_34458693: 其实本质上是sale操作已经正常结束了,while直接跳出后,num--,这个调用就结束了。
2 年多之前 回复
sinat_34458693
sinat_34458693 但是依旧无法发现问题,现在控制台显示直接没有调用sale线程了,望解答
2 年多之前 回复
sinat_34458693
sinat_34458693 您好,非常感谢您的回答,按照您的回答,我修改了代码如下
2 年多之前 回复
sinat_34458693
sinat_34458693   2016.03.29 16:17

class bread {
int num = 0;

public synchronized void makeBreand() {
    num++;
    this.notify();

}

public synchronized void sale() {

    while (num <= 0) {
        try {
            System.out.println("暂时无面包,等待");
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    num--;

}

}

class makeThread implements Runnable {
bread account;

public makeThread(bread s) {
    account = s;

}

public void run() {
    while (account.num < 10) {
        account.makeBreand();
        System.out.println("面包数量+1,已有" + account.num + "个面包");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}

class saleThread implements Runnable {
bread left;

public saleThread(bread s) {
    left = s;
}

public void run() {
    if (left.num > 0) {
        left.sale();
        System.out.println("售出面包一个   目前有" + left.num + "个面包");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}

boy_vansun
boy_vansun   2016.03.29 16:22

这个很显然,你的saleThread线程的run方法没有循环条件,里面的逻辑只会执行一次。
可能有些时候一次都不执行,这是因为saleThread可能会先于makeThread执行,此时left.num==0,run方法就结束了。

还有,bread的sale方法里面的while语句很奇怪,这个地方使用while与if有什么区别么?
还有,为什么类名都是小写的……

sinat_34458693
sinat_34458693 非常感谢您的回答,确实是这个问题!已经解决~以后类名我记得大写~
2 年多之前 回复
sinat_34458693
sinat_34458693 您好,非常感谢您的回答,我在saleThread 中给了循环条件while(num>0)调用sale(),但是结果还是一样。望解答!
2 年多之前 回复
guanjun_12
guanjun_12   2017.12.10 11:09

循环条件不对,应该用结束标志的

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
如何解决java线程中的资源共享的问题
更多相关的文章的链接:http://www.cnblogs.com/chenssy/p/4701027.html; 1.资源共享问题的产生:由于需要被访问的资源没有被合理地保护起来,所以在多线程都来访问这个资源的时候,很可能就会出现这个问题,从而导致产生了错误。比如下面的这个例子:其实可以这样理解:你坐在桌子的旁边,正要去叉盘子中的最后的一块事物,当你的叉子就要够着它的时候,这片事物突然就消失了
多线程Thread类和Runnable接口资源共享问题分析
最近在看多线程时,一直迷茫为什么继承Thread类的多线程不能实现资源共享,但是实现Runnable接口的多线程却能实现资源共享,先看一段经典的卖票多线程,将程序修改一下,使运行结果直观。 首先是实现Runnable接口来实现多线程:public class TicketSaleMain implements Runnable{ private int num = 5;
Java多线程如何实现资源共享
Java实现多线程方式有两种:继承Thread类或者实现Runnable即可.线程启动时调用start()方法. 实现Runnable接口可以实现资源共享 下面让我们来看一下代码:public class Thread1 extends Thread{ private int num = 5; @Override public void run() { for
Runnable可以实现资源共享但Thread不能实现资源共享的原因
转自:http://blog.csdn.net/javaniceyou/article/details/6859305 线程的两种实现方式,通过实现Runnable接口的线程方式可以实现资源的共享,而继承Thread则不可以,原因何在?先看下面两段代码: 通过Thread实现线程: Java代码  //使用Thread实现线程不能实现资源共享
多线程资源共享的问题
线程共享,线程同步
小白学c++之多线程共享资源
#include #include #include #include void* fun(void* arg); int main(int argc,const char* argv[]) { pthread_t thd; int* p=new int(1); pthread_create(&thd,NULL,fun,NULL); int i=0; for(;i<10;
实现Runnable,轻松实现多线程间的资源共享
实现Runnable,轻松实现多线程间的资源共享
java解决共享资源竞争
由于多线程的实现,在运行一个程序的时候可能会有很多的线程在同时运行,但是线程的调度并不是可见的,所以不会知道一个线程什么时候在运行,比如说 你坐在桌子前手拿着叉子,正要去叉盘中的最后一片食物,当你的叉子就要够得着他的时候,这片食物突然消失了,因为你的线程挂起了,另一个用餐者进入并吃掉了它,所以这就是在使用多线程时会出现的问题,对于并发的任务,你需要一种方式来防止两个线程同时访问一段资源,基本上所有...
java多线程之共享资源
先看一个示例, 多个计数器线程实例(TwoCounter), 每个实例有两个整型计数器,线程运行时,两个计数器开始"同时"累加,还有若干个监控器线程实例(Watcher),每个实例都会利用自己的"线程时间"监控所有的计数器实例,当某个实例中的count1和count2不相等时,就会显示"unsynched"。
java多线程(二)解决共享资源竞争
【博客为自己复习准备面试知识梳理、总结用,如有错误,望各路大神指正,不胜感激!】 1、问题的出现 /* * 这是一个整数生成器 * canceled 表示这个对象是否已被取消 * */ public abstract class IntGenerator { private volatile boolean canceled = false; public abstract int