Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this thread example work? It all wait()'s

The code below is to emulate a robotics simulator I'm working with. I'm not entirely sure why this doesn't work - I'm not very familiar with threads and even though I've tried reading plenty today, I don't seem to be making progress. The problem is that once pauseDistanceSensor() is called, it never wakes up.

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;
    }
}
like image 836
nathas Avatar asked May 13 '26 15:05

nathas


1 Answers

Your call to the 'pauseDistanceSensor' blocks the main thread on the wait call.

Also your sensor run method only sets the sensor value once; the run method should loop, setting the value each time.

Your pause method should instead call a synchronized method that suspends the sensor run loop, using a boolean flag or similar.

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();}
}
like image 139
sje397 Avatar answered May 16 '26 06:05

sje397



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!