0

以下程序执行基本的多线程任务。我在一个类中有两个线程。一个线程负责增加一个值变量,另一个线程负责检查该值并显示一条消息。

Class Was{
private int ctime;
private int value;
public Thread w,c;

public was(int a) {
    ctime=a;
    w = new Thread(new Runnable() {           
        public void run() { 
            try {
                for(int i=0;i<5;i++) {
                    Thread.sleep(ctime*1000);
                    value++; 
                }
                System.out.printf("\nIncreasing done");
            } catch(InterruptedException e) { 
                System.out.println(e);
            }
    } 
    });

    c = new Thread(new Runnable() {           
        public void run() { 
            try {
                for(;;) {
                    if(value==3) {
                        w.wait();
                        System.out.printf("\nValue reached");
                        w.notify();
                        break;
                    }
                }
            } catch(InterruptedException e) { 
                System.out.println(e);
            }
        } 
    });
}

main class

class Main{
    public static void main(String z[]) {
        Scanner s = new Scanner(System.in);
        int temp;
        System.out.printf("\nEnter the sleeping time in seconds: ");
        temp=s.nextInt();
        was m = new was(temp);
        m.w.start();
        m.c.start();
    }
}

c 线程永远不会告诉该值已达到。我不懂为什么。

4

3 回答 3

8

c 线程永远不会告诉该值已达到。我不懂为什么。

当您在线程之间共享值时,您需要使用某种机制来同步保存该值的内存。这可以通过一个synchronize块来完成,将值标记为volatile,或者使用(在这种情况下)一个AtomicInteger。这是关于内存一致性的一个很好的教程

AtomicInteger这里使用它是正确的,因为它允许线程安全地递增。您必须记住,增量不是原子操作,因为它实际上是 get、increment 和 set。

您的代码将类似于:

private final AtomicInteger value = new AtomicInteger(0);
...
value.incrementAndGet();
...
if (value.get() == 3) ...

此外,正如@Boris 指出的那样,您有以下代码:

w.wait();
System.out.printf("\nValue reached");
w.notify();

这不会编译,因为您不在一个synchronized块中。此外,先有一个wait()然后notify()是一个有点奇怪的模式。您可能还想阅读有关受保护块的教程

于 2013-10-18T12:06:13.257 回答
0

我对代码进行了更改,要求相同但设计不同。所以我的理解是线程 W 和 C 应该共享同一个监视器,当其他信号这样做时,一个监视器会通过它得到通知。所以在这种情况下,对象锁充当监视器。我将相同的对象(锁)实例传递给两个线程,并在该锁上调用等待和通知。它工作正常。包 com.stackoverflow.gin;

public class Main {

    private Object lock = new Object();
    private C c = new C(lock);
    private W w = new W(lock);

    public static void main(String[] args) {
        Main u = new Main();
        u.start();
    }

    public void start() {
        System.out.println("Start");
        c.start();
        w.start();
    }

    public class W extends Thread {
        private Object lock;

        public W(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    Thread.sleep(1000);
                    System.out.println("Notify C that I have finished work");
                    synchronized (lock) {
                        lock.notify();
                    }
                }
            } catch (Exception e) {
                System.out.println(e.getMessage() + "W");
            }
        }
    }

    public class C extends Thread {
        private int times = 0;
        private Object lock;

        public C(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    System.out.println("Waiting for W to finish ");
                    synchronized (lock) {
                        lock.wait();
                    }
                    System.out.println("W has notified " + times);
                    times++;
                    if (times == 3) {
                        System.out.println("Every thing is done, lets die to gether");
                        System.exit(0);

                    }
                }
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

}
于 2013-10-18T13:12:30.653 回答
0

我认为您不能也不应该让一个线程等待另一个线程。就像两辆公共汽车并行运行,一辆公共汽车想要在另一辆公共汽车上休息。那没有意义。或者它不是一个好的设计。我不知道以下是您要查找的内容,但请查看并告诉我。

import java.util.concurrent.atomic.AtomicInteger;

public class Main {

    private Object lock = new Object();
    private C c = new C(lock);
    private W w = new W(lock);
    private AtomicInteger times = new AtomicInteger();

    public static void main(String[] args) {
        Main u = new Main();
        u.start();
    }

    public void start() {
        System.out.println("Start");
        c.start();
        w.start();
    }

    public class W extends Thread {
        private Object lock;

        public W(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(1000);
                    times.set(i + 1);
                    System.out.println("Incremented counter " + times.get());
                }
                synchronized (lock) {
                    System.out.println("Notify C that I have finished work");
                    lock.notify();
                }
            } catch (Exception e) {
                System.out.println(e.getMessage() + "W");
            }
        }
    }

    public class C extends Thread {
        private Object lock;

        public C(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                for (;;) {
                    if (times.get() == 3) {
                        synchronized (lock) {
                            System.out.println("Now I will wait until W finishes with his work");
                            lock.wait();
                            System.out.println("Ok W is finished with the loop " + times.get() + " lets exit the sytem.");
                            System.exit(0);
                        }
                    }
                }
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

}
于 2013-10-19T07:24:22.200 回答