Seung
Seung

Reputation: 833

Things seems to be running parallel Java

I am fairly new to Java; (<= lol I just typed semicolon instead of dot (after 2 days of non-stop coding. Leaving it there so that everyone can laugh as well :D )

I wasn't sure what I was looking for, so the title is not very helpful.

Best I can describe is that things seems to run parallel. I am not sure how to explain this, so I'll show you an example. I have a timer class that waits for a duration each loop.

If I run the following method(not in the timer class, but just another one), it doesn't wait until the Runnable part(Timer) is finished like for loop would do. It computes the code below at the same time.

How can I make the program to wait for the Timer to finish? Also, why is it running parallel?

I trimmed most of the unnecessary codes but please ask if you need the whole code.

t = Timer;
public void turnend() {
    if (leftover == 0) {
        housenumber = 1;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                //code1
                if (housenumber == 8) {
                    t.stopTimer();
                }
            }
        };
        t = new Timer(r, 500, true);
    }
    //code 2
}
//code 1 and 2 runs at the same time

EDIT: Timer class

import android.os.Handler;

public class Timer {
private Handler handler;
private boolean paused;

private int interval;

private Runnable task = new Runnable () {
    @Override
    public void run() {
        if (!paused) {
            runnable.run ();
            Timer.this.handler.postDelayed (this, interval);
        }
    }
};

private Runnable runnable;

public int getInterval() {
    return interval;
}

public void setInterval(int interval) {
    this.interval = interval;
}

public void startTimer () {
    paused = false;
    handler.postDelayed (task, interval);
}

public void stopTimer () {
    paused = true;
}

public Timer (Runnable runnable, int interval, boolean started) {
    handler = new Handler ();
    this.runnable = runnable;
    this.interval = interval;
    if (started)
        startTimer ();
}

}

Upvotes: 1

Views: 325

Answers (2)

zapl
zapl

Reputation: 63955

Android's main thread looks a bit like

while (true) {
    Runnable nextThingToDo = getNextTaskFromQueue();
    nextThingToDo.run();
}

and Handlers are used to put a new task into the queue. All the code you write in on???? methods like Activity#onCreate is also part of such tasks. Things like touch event handling & drawing updates of the screen appear in that queue too. You must therefore never pause that thread, the only way to do things "later" is to enqueue it for later (the queue is not a simple first-in-first-out queue, it supports delays and such)

Now, your Timer schedules the task Runnable to run after a set delay. Since the code that calls handler.postDelayed is necessarily already inside such a runnable itself it needs to be done before the queue can take and run task. So what happens in the unrolled while loop is roughly

Runnable nextThingToDo = getNextTaskFromQueue(); 
nextThingToDo.run();
// inside above "run"... whatever code path leads to turnend()
    if (leftover == 0) {
        housenumber = 1;
        Runnable r = construct();// it's only a reference to a `Runnable` object, nothing executes here
        t = new Timer(r, 500, true);
        // inside Timer
            handler.postDelayed(task, 500); // task is now in the queue
    }
    //code 2 -- it actually runs now.
// whatever else is in your code on the way out from "turnend()"

// ... things happen, 500ms passes

Runnable nextThingToDo = getNextTaskFromQueue(); // this is the `task` object
nextThingToDo.run();
// inside this "run"
    if (!paused) {
        runnable.run (); // this is the `r` object
        // inside task
           {
            // code1 -- running ~ 500ms after code2
            if (housenumber == 8) {
                t.stopTimer();
            }
          }

To solve your problem, you should first of all understand that writing code that happens in multiple steps over time is not straight & simple and it needs to be written so that code always triggers future code, a neverending series of events. Code can not wait on future tasks to complete, you can only tell the future code what you want to do once it's done.

For example by moving the code physically into the place where it belongs:

public void turnend() {
    if (leftover == 0) {
        housenumber = 1;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                //code1
                if (housenumber == 8) {
                    t.stopTimer();
                }
                //code 2
            }
        };
        t = new Timer(r, 500, true);
    }
}

Or by providing the future code with a reference to code you want to be called, this is what is called a "callback". In it's simplest form:

    public void turnend() {
        final Runnable callback = new Runnable() {
            @Override
            public void run() {
                //code 2
            }
        };

        if (leftover == 0) {
            housenumber = 1;
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    //code1
                    if (housenumber == 8) {
                        t.stopTimer();
                    }
                    callback.run();
                }
            };
            t = new Timer(r, 500, true);
        }
    }

Everytime you want to write

    public void things() {
        // code 1
        // delay of 500
        // code 2
    }

Instead do roughly:

    public void thingsPart1() {
        // code1

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                thingsPart2();
            }
        }, 500);
    }

    public void thingsPart2() {
        // code 2
    }

Upvotes: 1

Toilal
Toilal

Reputation: 3409

If you want to block the current Thread, you should use Thread.sleep(500) static method instead of a Timer.

Upvotes: 1

Related Questions