cur*_*zen 5 java multithreading android sleep
这个要求出现在我的Android应用程序中,但它一般适用于Java.我的应用程序每隔几秒就"做一些事".我已经实现了如下(只是相关的片段 - 不是完整的代码):
Snippet1:
public class PeriodicTask {
private boolean running = true;
private int interval = 5;
public void startTask(){
while (running){
doSomething();
try{
Thread.sleep(interval * 1000);
} catch(InterruptedException e){
//Handle the exception.
}
}
}
public void stopTask(){
this.running = false;
}
public void setInterval(int newInterval){
this.interval = newInterval;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这种方法的问题是setInterval()不会立即生效.它仅在前一个sleep()完成后生效.
由于我的用例允许最终用户以固定步长(1秒 - 从1到60秒)设置间隔,因此我将实现修改为在循环内休眠; 并按如下方式每秒检查新的间隔值:
Snippet2:
public class PeriodicTask {
private boolean running = true;
private int interval = 5;
private int loopCounter = 0;
public void startTask(){
while (running){
doSomething();
try{
while(loopCounter < interval) {
Thread.sleep(1 * 1000);
loopCounter ++;
}
} catch(InterruptedException e){
//Handle the exception.
}
}
}
public void stopTask(){
this.running = false;
}
public void setInterval(int newInterval){
synchronized (this) {
this.interval = newInterval;
if(newInterval < loopCounter){
loopCounter = 0;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有理由不使用这种方法?
我最近interrupt()为此目的遇到了这种方法.但是,我无法弄清楚如何使用它.首先,中断方法与睡眠方法不同static.那么,Thread我该打断什么?
public void setInterval(int newInterval){
this.interval = newInterval;
//What thread do I call interrupt() on?
}
Run Code Online (Sandbox Code Playgroud)
其次,如果我成功中断了睡眠Thread,我相信会执行该catch块InterruptedException.但是,此时我需要startTask()再次打电话.关于这个递归的终止,我很困惑.关于trunk()的使用,我已经经历了几个关于SO的问题,但是找不到任何可以帮助我的东西.
有什么指针吗?
我的应用程序每隔几秒钟使用REST调用获取一些值.更新间隔可由用户配置.
现在,假设更新间隔已设置为60秒.我发布的Snippet1工作(错误)如下:
PeriodicTask只能看到经过60秒的已经过期了新的更新间隔.确切的要求是新的更新间隔应该立即生效(或者至少在设置后不迟于1秒 - 因为这是用户可能感知到的).
我的Snippet2和Snippet3试图达到这个要求.
Mar*_*mes 11
IIRC,在Java中你可以使用超时对象.wait().这不是你想要的吗?如果要更改另一个线程的超时,请更改一些'waitValue'变量并通知().然后线程将"立即"运行,然后再次使用新的超时值.无需明确睡眠.
这个答案帮助我完成了这项工作.发布一些关于我如何实现它的代码.特别重要的是startTask()和setInterval().
public class PeriodicTask {
private volatile boolean running = true;
private volatile int interval = 5;
private final Object lockObj = new Object();
public void startTask() {
while (running) {
doSomething();
synchronized (lockObj) {
try{
lockObj.wait(interval * 1000);
} catch(InterruptedException e){
//Handle Exception
}
}
}
}
public void stopTask() {
this.running = false;
}
public void setInterval(int newInterval) {
synchronized (lockObj) {
this.interval = newInterval;
lockObj.notify();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不清楚你真正想做什么.你的目标是停止在PeriodicTask中运行循环的线程,还是只想打破循环并允许线程继续?如果您只想打破循环但允许线程继续,请考虑以下示例:
public class ThreadStopExample {
public static void main ( String[] args ) throws InterruptedException {
final PeriodicTask task = new PeriodicTask ();
Thread t = new Thread ( new Runnable () {
@Override
public void run () {
System.out.println ( Thread.currentThread ().getName ()
+ " starting" );
task.startTask ();
System.out.println ( Thread.currentThread ().getName ()
+ " done with the periodic task" );
}
} );
t.start ();
Thread.sleep ( 12000 );
task.setInterval ( 1 );
Thread.sleep ( 3000 );
task.stopTask ();
}
static class PeriodicTask {
private volatile boolean running = true;
private volatile int interval = 5;
public void startTask () {
running = true;
while ( running ) {
doSomething ();
try {
int count = 0;
while ( running && count++ < interval ) {
Thread.sleep ( 1000 );
}
} catch ( InterruptedException e ) {
Thread.currentThread ().interrupt ();
running = false;
break;
}
}
}
public void stopTask () {
running = false;
}
public void setInterval ( int newInterval ) {
interval = newInterval;
}
private void doSomething () {
System.out.println ( "[" + Thread.currentThread ().getName ()
+ "] Interval: " + interval );
}
}
}
Run Code Online (Sandbox Code Playgroud)
这与您现有的代码非常相似.请注意volatile字段,以确保运行PeriodicTask循环的线程与尝试更改间隔和停止任务的主线程之间的正确同步(请参阅此处获取有关java内存模型的更多信息的链接).如您所见,在调用停止任务之后,继续使用PeriodicTask实例的线程.另请注意,PeriodicTask在收到中断的异常时会调用当前线程的中断.这确保了在当前线程上设置了中断标志,以便任何外部代码都能够看到中断并做出适当的反应,例如,不是打印完成,运行PeriodicTask的线程可能已经检查了自身的中断状态并做了一些有趣的事情.
如果您的目标是停止线程本身,那么您可能希望使用PeriodicTask扩展Thread,除非您有充分的理由这样做,否则不推荐使用,或者让PeriodicTask实现Runnable.考虑下一个例子:
public class ThreadStopExample2 {
public static void main ( String[] args ) throws InterruptedException {
final PeriodicTask task = new PeriodicTask ();
Thread t = new Thread ( task );
t.start ();
Thread.sleep ( 12000 );
task.setInterval ( 1 );
Thread.sleep ( 3000 );
t.interrupt ();
}
static class PeriodicTask implements Runnable {
private volatile int interval = 5;
@Override
public void run () {
while ( true ) {
doSomething ();
try {
int count = 0;
while ( count++ < interval ) {
Thread.sleep ( 1000 );
}
} catch ( InterruptedException e ) {
Thread.currentThread ().interrupt ();
break;
}
}
}
public void setInterval ( int newInterval ) {
interval = newInterval;
}
private void doSomething () {
System.out.println ( "[" + Thread.currentThread ().getName ()
+ "] Interval: " + interval );
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里,PeriodicTask处于忙循环中,直到运行它的线程被中断.中断用于指示PeriodicTask退出循环,然后允许线程在run方法结束时完成.
关于你的两个明确的问题:不,如果你不打算控制执行线程,我没有看到使用PeriodicTask的任何实际问题,例如,可能池中的线程运行PeriodicTask的实例(但确保修复您的代码以便正确同步),并且,当使用中断时,您可以在要中断的线程的实例上调用它.如何获得对该线程的引用取决于您的系统.
| 归档时间: |
|
| 查看次数: |
36475 次 |
| 最近记录: |