如何在Android中以规定的时间间隔运行可运行线程?
我开发了一个应用程序,在Android emulator屏幕上以规定的间隔显示一些文本。我正在使用如何在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); 运行此应用程序时,文本仅显示一次
处理程序
类。以下是我的代码片段:
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.分析
- 在上述成本中,假设
costT毫秒,显示500次后延迟时间为500*T毫秒tv.append(“Hello Word”)
- 长时间运行会增加延迟
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不为null)myTimer.cancel()
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")
}
}