Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android中以规定的时间间隔运行可运行线程?_Android_Multithreading - Fatal编程技术网

如何在Android中以规定的时间间隔运行可运行线程?

如何在Android中以规定的时间间隔运行可运行线程?,android,multithreading,Android,Multithreading,我开发了一个应用程序,在Android emulator屏幕上以规定的间隔显示一些文本。我正在使用处理程序类。以下是我的代码片段: handler = new Handler(); Runnable r = new Runnable() { public void run() { tv.append("Hello World"); } }; handler.postDelayed(r, 1000); 运行此应用程序时,文本仅显示一次

我开发了一个应用程序,在Android emulator屏幕上以规定的间隔显示一些文本。我正在使用
处理程序
类。以下是我的代码片段:

handler = new Handler();
Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");               
    }
};
handler.postDelayed(r, 1000);

运行此应用程序时,文本仅显示一次。为什么?

对您的示例的简单修复是:

handler = new Handler();

final Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");
        handler.postDelayed(this, 1000);
    }
};

handler.postDelayed(r, 1000);
或者我们可以使用普通线程,例如(使用原始Runner):

您可以将可运行对象视为可以发送到消息队列执行的命令,而处理程序只是用来发送该命令的助手对象。


更多细节在这里

我认为可以改进Alex2k8的第一个解决方案,以便每秒钟进行正确更新

1.原始代码:

public void run() {
    tv.append("Hello World");
    handler.postDelayed(this, 1000);
}
2.分析

  • 在上述成本中,假设
    tv.append(“Hello Word”)
    costT毫秒,显示500次后延迟时间为500*T毫秒
  • 长时间运行会增加延迟
3。解决方案

要避免这种情况,只需更改postDelayed()的顺序即可,要避免延迟,请执行以下操作:

public void run() {
    handler.postDelayed(this, 1000);
    tv.append("Hello World");
}

如果我正确理解Handler.post()方法的文档:

导致将可运行r添加到消息队列。runnable将在该处理程序所连接的线程上运行

因此@alex2k8提供的示例,即使工作正常,也不相同。 在使用
Handler.post()
的情况下,不会创建新线程。您只需将
Runnable
发布到带有
Handler
的线程,该线程将由执行。 在此之后,EDT只执行
Runnable.run()
,而不执行其他操作

记住:
Runnable!=线程

我认为对于这种典型的情况,即以固定的时间间隔运行某个东西,
计时器
更合适。下面是一个简单的例子:

myTimer = new Timer();
myTimer.schedule(new TimerTask() {          
@Override
public void run() {
    // If you want to modify a view in your Activity
    MyActivity.this.runOnUiThread(new Runnable()
        public void run(){
            tv.append("Hello World");
        });
    }
}, 1000, 1000); // initial delay 1 second, interval 1 second
使用
计时器
的优点不多:

  • 初始延迟和间隔可以在
    计划
    函数参数中轻松指定
  • 只需调用
    myTimer.cancel()
  • 如果只想运行一个线程,请记住在调度新线程之前调用
    myTimer.cancel()
    (如果myTimer不为null)

对于重复任务,您可以使用

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
就像

new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

            }
        },500,1000);
上述代码将在半秒(500)后第一次运行,并在每秒(1000)后重复运行

在哪里

任务是要执行的方法

初始执行时间之后

间隔重复执行的时间)

其次

如果要执行任务多次,还可以使用倒计时

    new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

     public void onTick(long millisUntilFinished) {
      }
      public void onFinish() {
     }
    }.start();

//Above codes run 40 times after each second
你也可以用runnable来做。创建一个可运行的方法,如

Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {

        }
    };
用这两种方式来称呼它

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread

new Thread(runnable).start();//to work in Background 

一个有趣的例子是,您可以连续看到计数器/秒表在单独的线程中运行。还显示GPS位置。而主活动用户界面线程已经存在

摘录:

try {    
    cnt++; scnt++;
    now=System.currentTimeMillis();
    r=rand.nextInt(6); r++;    
    loc=lm.getLastKnownLocation(best);    

    if(loc!=null) { 
        lat=loc.getLatitude();
        lng=loc.getLongitude(); 
    }    

    Thread.sleep(100); 
    handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {   
    Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
要查看代码,请参见此处:


现在在Kotlin中,您可以通过以下方式运行线程:

class SimpleRunnable: Runnable {
    public override fun run() {
        println("${Thread.currentThread()} has run.")
    }
}
fun main(args: Array<String>) {
    val thread = SimpleThread()
    thread.start() // Will output: Thread[Thread-0,5,main] has run.
    val runnable = SimpleRunnable()
    val thread1 = Thread(runnable)
    thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
class SimpleRunnable:可运行{
公共超控趣味跑(){
println(“${Thread.currentThread()}已运行。”)
}
}
趣味主线(args:Array){
val thread=SimpleThread()
thread.start()//将输出:thread[thread-0,5,main]已运行。
val runnable=SimpleRunnable()
val thread1=线程(可运行)
thread1.start()//将输出:Thread[Thread-1,5,main]已运行
}
Kotlin JAVA 科特林与合作项目 在Kotlin中,使用协程可以执行以下操作:

CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
    ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
        tv.append("Hello World")
    }
}

试试看

Alex,我有一个小小的疑问。现在线程运行良好,并连续显示文本,如果我想停止,这意味着我必须做什么?请帮助我。你可以定义布尔变量_stop,并在你想停止时将其设置为“true”。并将“while(true)”更改为“while(!\u stop)”,或者如果使用了第一个示例,则只需更改为“if(!\u stop)handler.postDelayed(this,1000)”。如果要确保处理程序将连接到主线程,则应按如下方式初始化:handler=new handler(Looper.getMainLooper())@alex2k8在第二个代码段中不应该是handler.post(r)而不是handler.post(this)?此外,如果要将解决方案用于线程,还必须从Runnable r中删除handler.postDelayed(这是1000),因为延迟已经在Thread对象的run()方法内部执行。@alex2k8-Hi bro!请告诉我如何在运行时手动停止第二个代码段
线程
?-1您假设在run()中执行的任务每次运行的成本是固定的,如果这是对动态数据的操作(通常是这样),那么您将一次发生多个run()。这就是postDelayed通常放在末尾的原因。@Jay很遗憾,您错了。处理程序与单个线程(以及作为该线程的运行方法的循环器)+消息队列相关联。每次发布消息时,都会将其排队,下次循环器检查队列时,它会执行发布的Runnable的run方法。因为这一切都发生在一个线程中,所以不能同时执行多个线程。另外,先执行postDelayed将使每次执行更接近1000毫秒,因为它在内部使用当前时间+1000作为执行时间。如果将代码放在post之前,则会增加额外的延迟。@zapl感谢关于处理程序的提示,我认为它将执行多个可运行程序,因此会执行多个线程。然而,在内部,当运行持续时间小于或等于1000ms时,if((currenttime-lastruntime)>1000)等条件可以正常工作
try {    
    cnt++; scnt++;
    now=System.currentTimeMillis();
    r=rand.nextInt(6); r++;    
    loc=lm.getLastKnownLocation(best);    

    if(loc!=null) { 
        lat=loc.getLatitude();
        lng=loc.getLongitude(); 
    }    

    Thread.sleep(100); 
    handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {   
    Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
class SimpleRunnable: Runnable {
    public override fun run() {
        println("${Thread.currentThread()} has run.")
    }
}
fun main(args: Array<String>) {
    val thread = SimpleThread()
    thread.start() // Will output: Thread[Thread-0,5,main] has run.
    val runnable = SimpleRunnable()
    val thread1 = Thread(runnable)
    thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
    val handler = Handler()
    runnable = Runnable {
        // do your work
        handler.postDelayed(runnable, 2000)
    }
    handler.postDelayed(runnable, 2000)
}
Runnable runnable;
Handler handler;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            // do your work
            handler.postDelayed(this, 1000);
        }
    };
    handler.postDelayed(runnable, 1000);
}
CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
    ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
        tv.append("Hello World")
    }
}