事情似乎与Java并行运行

时间:2016-05-23 06:29:32

标签: java android android-studio runnable

我对Java很新; (< = lol我只输入分号而不是点(经过2天的不间断编码。将它留在那里以便每个人都可以笑:D)

我不确定我在寻找什么,所以标题不是很有帮助。

我能描述的最好的事情似乎并行。 我不知道如何解释这个,所以我给你举个例子。 我有一个计时器类,每个循环等待一段时间。

如果我运行以下方法(不在计时器类中,而只是在另一个方法类中),它不会等到Runnable部分(Timer)完成,就像循环那样。它同时计算下面的代码。

如何让程序等待Timer完成?另外,为什么它并行运行?

我修剪了大部分不必要的代码,但请问你是否需要整个代码。

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

编辑:计时器类

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 ();
}

}

2 个答案:

答案 0 :(得分:1)

如果要阻止当前线程,则应使用Thread.sleep(500)静态方法而不是Timer。

答案 1 :(得分:1)

Android的主要线程看起来有点像

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

Handler用于将新任务放入队列。您在on????方法中编写的所有代码(如Activity#onCreate)也是此类任务的一部分。像触摸事件处理和事件;画面的更新也会出现在该队列中。因此,你必须永远不要暂停那个线程,这是做事情的唯一方法。"之后"是为了以后将它排队(队列不是简单的先进先出队列,它支持延迟等)

现在,您的Timer计划task Runnable在设定的延迟后运行。由于调用handler.postDelayed的代码必须已经在这样的runnable本身内部,因此需要在队列可以执行并运行task之前完成。那么在展开的while循环中发生的事情大致是

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();
            }
          }

要解决您的问题,首先应该明白,编写随时间推移的多个步骤的代码并不是直接的。简单,需要编写代码,以便代码始终触发未来的代码,这是一系列无休止的事件。代码不能等待将来的任务完成,你只能告诉将来代码你想要做的事情。

例如,将代码物理地移动到它所属的位置:

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);
    }
}

或者通过为将来的代码提供您想要调用的代码的引用,这就是所谓的"回调"。用它最简单的形式:

    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);
        }
    }

每次你想写

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

而是大致:

    public void thingsPart1() {
        // code1

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

    public void thingsPart2() {
        // code 2
    }