Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.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/android/226.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
Java 唤醒睡眠线程-中断()与;“拆分”;将睡眠分为多次睡眠_Java_Android_Multithreading_Sleep - Fatal编程技术网

Java 唤醒睡眠线程-中断()与;“拆分”;将睡眠分为多次睡眠

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

这一要求出现在我的Android应用程序中,但它一般适用于Java。我的应用每隔几秒钟就“做点什么”。我实现了以下内容(只是相关的代码片段-不是完整的代码):

代码片段1:

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秒。线还在睡觉
  • PeriodicTask
    仅在60秒过期后才会看到新的更新间隔
确切的要求是,新的更新间隔应该立即生效(或者至少不迟于设置后的1秒,因为这是用户无论如何都可能感知到的)

我的Snippet2和Snippet3是为了达到这个要求而进行的尝试。

您在正在睡眠的线程上调用
中断()
,它将抛出一个
中断异常,您在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{
期末