为什么这个线程示例不起作用?这一切都等待()

时间:2010-06-23 00:21:12

标签: java multithreading concurrency

下面的代码是模拟我正在使用的机器人模拟器。我不完全确定为什么这不起作用 - 我对线程不是很熟悉,即使我今天尝试阅读很多,但我似乎并没有取得进展。问题是,一旦调用pauseDistanceSensor(),它就永远不会被唤醒。

import java.util.Random;

public class TestThreads
{
    private DistanceSensor dist;
    private Thread distanceThread;
    public TestThreads()
    {
        this.dist = new DistanceSensor();
        this.distanceThread = new Thread(this.dist);
        this.distanceThread.start();
    }

    public int getDistance()
    {
        return this.dist.getMeasurement();
    }

    public void pauseDistanceSensor()
    {
        synchronized(this.dist)
        {
            try {
                this.dist.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public void resumeDistanceSensor()
    {
        synchronized(this.dist)
        {
            this.dist.notify();
        }
    }

    public static void main(String[] args)
    {
        TestThreads test = new TestThreads();
        long timestamp = System.currentTimeMillis();
        System.out.println("Starting at "+timestamp);
        System.out.println("1: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("2: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("waiting distance sensor and making 3 getDistance calls then sleeping main thread for 1 second - all 3 getDistance calls should be printed when the sleep ends");
        test.pauseDistanceSensor();
        System.out.println("3: "+test.getDistance());
        System.out.println("4: "+test.getDistance());
        System.out.println("5: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Alive! Notifying the thread");
        test.resumeDistanceSensor();
        System.out.println("Done at "+System.currentTimeMillis());
    }
}

class DistanceSensor implements Runnable
{
    private final Random gen = new Random(54);
    private int currentVal;
    public DistanceSensor()
    {
        this.currentVal = this.gen.nextInt(1500);
    }

    public void run()
    {
        this.currentVal = this.gen.nextInt(1500);
    }

    public int getMeasurement()
    {
        return this.currentVal;
    }
}

1 个答案:

答案 0 :(得分:4)

您对'pauseDistanceSensor'的调用会阻止等待呼叫中的主线程。

此外,您的传感器运行方法仅设置传感器值一次; run方法应该循环,每次都设置值。

你的pause方法应该调用一个使用布尔标志或类似方法挂起传感器运行循环的synchronized方法。

import java.util.Random;

public class TestThreads
{
    private DistanceSensor dist;
    private Thread distanceThread;
    public TestThreads()
    {
        this.dist = new DistanceSensor();
        this.distanceThread = new Thread(this.dist);
        this.distanceThread.start();
    }

    public int getDistance()
    {
        return this.dist.getMeasurement();
    }

    public void pauseDistanceSensor()
    {
      dist.setPaused(true);
    }

    public void resumeDistanceSensor()
    {
      dist.setPaused(false);
    }

    public void finish() {
      dist.setDone();
    }

    public static void main(String[] args)
    {
        TestThreads test = new TestThreads();
        long timestamp = System.currentTimeMillis();
        System.out.println("Starting at "+timestamp);
        System.out.println("1: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("2: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("waiting distance sensor and making 3 getDistance calls then sleeping main thread for 1 second - all 3 getDistance calls should be printed when the sleep ends");
        test.pauseDistanceSensor();
        System.out.println("3: "+test.getDistance());
        System.out.println("4: "+test.getDistance());
        System.out.println("5: "+test.getDistance());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Alive! Notifying the thread");
        test.resumeDistanceSensor();
        System.out.println("Done at "+System.currentTimeMillis());
        test.finish();
    }
}

class DistanceSensor implements Runnable
{
    private final Random gen = new Random(54);
    private int currentVal;
    private boolean done = false, paused = false;
    public DistanceSensor()
    {
        this.currentVal = this.gen.nextInt(1500);
    }

    public void run()
    {
        while(!getDone()) {
          if(!getPaused()) synchronized(this) {this.currentVal = this.gen.nextInt(1500);}
          synchronized(this) {
            try {
              wait(500);
            } catch(InterruptedException ex) {
              ex.printStackTrace();
            }
          }
        }
    }

    public synchronized int getMeasurement()
    {
        return this.currentVal;
    }

    public synchronized boolean getPaused() {return paused;}
    public synchronized boolean getDone() {return done;}
    public synchronized void setPaused(boolean p) {paused = p;}
    public synchronized void setDone() {done = true;notify();}
}