Java 唤醒睡眠线程-中断()与;“拆分”;将睡眠分为多次睡眠
这一要求出现在我的Android应用程序中,但它一般适用于Java。我的应用每隔几秒钟就“做点什么”。我实现了以下内容(只是相关的代码片段-不是完整的代码): 代码片段1:Java 唤醒睡眠线程-中断()与;“拆分”;将睡眠分为多次睡眠,java,android,multithreading,sleep,Java,Android,Multithreading,Sleep,这一要求出现在我的Android应用程序中,但它一般适用于Java。我的应用每隔几秒钟就“做点什么”。我实现了以下内容(只是相关的代码片段-不是完整的代码): 代码片段1: public class PeriodicTask { private boolean running = true; private int interval = 5; public void startTask(){ while (running){ d
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;
}
}
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;
}
}
}
}
正如您所看到的,这种方法的问题在于setInterval()不能立即生效。它仅在上一个sleep()完成后生效
因为我的用例允许最终用户以固定的步骤设置间隔(1秒-从1秒到60秒),所以我修改了实现,使其在循环中休眠;并按如下方式每秒检查一次新的间隔值:
代码片段2:
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;
}
}
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;
}
}
}
}
其次,如果我成功地中断了休眠的线程
,我相信中断异常
的捕获
块将被执行。但是,此时我需要再次调用startTask()
。我对这个递归的终止感到困惑。关于interrupt()的使用,我已经讨论了几个问题,但是找不出任何有帮助的方法
有什么建议吗
编辑-有关确切要求的更多详细信息: 我的应用程序每隔几秒钟使用REST调用获取一些值。用户可以配置更新间隔 现在,假设更新间隔已设置为60秒。我发布的代码片段1的工作原理(不正确)如下:
- 线程进入睡眠状态60秒
- 现在,假设用户将更新间隔更改为5秒。线还在睡觉
仅在60秒过期后才会看到新的更新间隔PeriodicTask
中断()
,它将抛出一个中断异常,您在catch块中处理该异常。然后你有了新的间歇时间,你可以循环,然后继续睡觉。如果捕获并处理InterruptedException
让我提供几个创建和中断线程的示例链接,因为从您的评论中,您似乎遗漏了一些重要的想法。请仔细阅读这些内容,然后您应该了解实现您要求的标准方法
http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html我不清楚你到底想做什么。您的目标是停止在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 );
}
}
}
公共类ThreadStopExample{
公共静态void main(字符串[]args)引发InterruptedException{
最终PeriodicTask任务=新PeriodicTask();
线程t=新线程(新可运行(){
@凌驾
公开作废运行(){
System.out.println(Thread.currentThread().getName()
+“启动”);
task.startTask();
System.out.println(Thread.currentThread().getName()
+“完成定期任务”);
}
} );
t、 开始();
睡眠(12000);
task.setInterval(1);
睡眠(3000);
task.stopTask();
}
静态类周期任务{
private volatile boolean running=true;
私有volatile int interval=5;
公共无效startTask(){
运行=真;
(跑步时){
doSomething();
试一试{
整数计数=0;
while(运行&&count++
这与您现有的代码非常相似。请注意volatile字段,以确保运行PeriodicTask循环的线程与尝试更改间隔和停止任务的主线程之间正确同步(有关java内存模型的更多信息,请参阅链接)。如您所见,在调用停止任务后,与PeriodictTask实例一起工作的线程将继续。另外,请注意,PeriodictTask在接收到中断的异常时将调用当前线程上的中断。这可确保在当前线程上设置中断标志,以便任何外部代码都能看到中断并做出适当反应,例如,运行PeriodicTask的线程可能检查了自身的中断状态并做了一些有趣的事情,而不是打印完成
如果您的目标是停止线程本身,那么您可能希望让PeriodictTask扩展线程,除非您有充分的理由这样做,否则不建议这样做,或者让PeriodictTask实现可运行。考虑下一个例子:
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 );
}
}
}
公共类ThreadStopExample2{
公共静态void main(字符串[]args)引发InterruptedException{
期末