等待并通知行为异常,线程被挂起

时间:2019-01-30 19:46:56

标签: java multithreading

下面是代码示例:使用5或6个值后,线程被挂起 我不知道我在哪里丢失任何东西。还有一个疑问,我是关于调用MyIncrementor类的构造函数的。最初,我试图通过创建MyIncrementor类的新对象来调用Producer和Consumer类中的get和set,但它也无法正常工作

/**
 * 
 */
package multithreadingDemo;

/**
 * @author Aquib
 *
 */
public class ThreadCommDemo {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        MyIncrementor mi=new MyIncrementor();
        Producer1 p=new Producer1(mi);
        Consumerrs c=new Consumerrs(mi);
        Thread t1=new Thread(p);
        Thread t2=new Thread(c);
        t1.start();
        t2.start();


    }

}



class MyIncrementor {
    int myCount;
    boolean valueSet;

    /**
     * @return the myCount
     */
    public synchronized int getMyCount() {
        if (!valueSet) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("get" + myCount);
        valueSet = true;
        notifyAll();
        return myCount;
    }

    /**
     * @param myCount
     *            the myCount to set
     */
    public synchronized void setMyCount(int myCount) {
        if (valueSet) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("Set" + myCount);
        this.myCount = myCount;
        valueSet = false;
        notifyAll();
    }

}

class Producer1 implements Runnable {
    MyIncrementor mi;

    public Producer1(MyIncrementor mi) {
        // TODO Auto-generated constructor stub
        this.mi=mi;
    }

    public void run() {

        for (int i = 1; i < 10; i++) {
            mi.setMyCount(i);
            System.out.println("Produced" + mi.myCount);
             try 
             {
                   Thread.currentThread().sleep((int)(Math.random() * 100));
             } 
             catch (InterruptedException ie) 
             {
                   ie.printStackTrace();
             }
        }
    }
}

class Consumerrs implements Runnable {
    MyIncrementor mi;

    public Consumerrs(MyIncrementor mi) {
        // TODO Auto-generated constructor stub
        this.mi=mi;
    }

    public void run() {

        for (int i = 1; i < 10; i++) {
            int val = mi.getMyCount();
            System.out.println("Consumed" + val);
        }

    }

}

2 个答案:

答案 0 :(得分:4)

首先要突出的是缺少while

    if (valueSet) { // <-- if is wrong
        try {
            wait();

wait应该在while中。这样可以确保条件得到满足,而不是出于其他某种原因或根本没有理由唤醒。

    while (valueSet) {
        try {
            wait();

大概是问题出在错误的方向上。

    if (!valueSet) {
        // ...
    }
    // ...
    valueSet = true;

假设if(应该是while)的目的是valueSettrue,但是随后您用true覆盖了true而不是修改变量。

Thread.sleep也是静态方法。在实例上调用它会产生令人难以置信的误导(尽管是一个常见错误)。

Thread.currentThread().sleep(/* ... */); // misleading

应该是

Thread.sleep(/* ... */);

答案 1 :(得分:2)

您在MyIncrementor类中仅存在逻辑错误,您错误地设置了valueSet,因此您必须更改条件或在getMyCount和{{ 1}}方法。

因此,这是setMyCount的正确版本:

MyIncrementor