Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.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_Multithreading - Fatal编程技术网

Java 关于长时间的任务中断,我如何解决这个多任务场景?

Java 关于长时间的任务中断,我如何解决这个多任务场景?,java,multithreading,Java,Multithreading,好的,我在一次采访中被问到这个多线程问题。问题是这样的 public class Job { static boolean interruptTask = false; private static class Mytask extends Thread{ @Override public void run() { while(!interruptTask){ //do some time

好的,我在一次采访中被问到这个多线程问题。问题是这样的

public class Job {

    static boolean interruptTask = false;

    private static class Mytask extends Thread{
        @Override
        public void run() {
            while(!interruptTask){
                //do some time consuming thing until interruption like looping over millions of times

            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Mytask t = new Mytask();
        t.run();
        Thread.sleep(1000);
        interruptTask=true;
        t.join();
        System.out.println("end");
    }
}
问题陈述

此代码段有什么问题,您将如何修复它。

我在这里发现了问题。我认为问题在于,即使我们在main函数中使interrupttask变量为true,它也不会中断线程。线程将继续执行,直到长时间的执行结束

但是我想不出解决这个问题的办法?我的意思是,我们有一些工具,比如等待,通知线程,但我不认为这些是我们可以在这里使用的东西。在这种情况下,解决这个特定问题的方法应该是什么


有人能帮我找出这个问题的解决办法吗?或者一些关于我应该如何着手解决问题的指导

与所讨论的变化相关地改变了答案

编辑后

private static class Mytask extends Thread{
  public void run(){

     while(true){
       if(Thread.currentThread().isInterrupted()){
          System.out.println("Thread Interrupted");
          break;  
       }
        //do stuff here
     }
  }
}

public static void main(String[] args) throws InterruptedException {
    Mytask t = new Mytask();
    t.start();
    try{
       Thread.sleep(1000);
    }catch(InterruptedException e){

    }
    System.out.println("Interrupting now");
    t.interrupt();
    System.out.println("end after interruption");
}

一个简单的解决方案是确保“长时间运行”任务定期中断,以允许另一个线程设置中断标志。通常,这是通过在预定的时间间隔后“睡眠”一小段时间来完成的。您还希望能够对“长时间运行”的代码进行分段。下面是伪代码

   // interruptTask should be declared like volatile boolean interruptTask
    long interval = <in milliseconds>
    long lastPause = <system time>
    while(!interruptTask){
        if (<time now> - lastPause > interval) {
            sleep(pausePeriod);
            lastPause = <system time>
        } else {
          ... long running work increment (not do this a billion times)
        }
    }
//interruptTask应该像volatile boolean interruptTask一样声明
长间隔=
长最后暂停=
while(!interruptTask){
如果(-lastPause>interval){
睡眠(暂停期);
最后暂停=
}否则{
…长时间运行的工作增量(不是10亿次)
}
}

有两个问题:

  • t.run()
    应该是
    t.start()
    。否则,这两项任务都是在单线程中完成的

  • interruptTask
    应该是
    volatile
    或者应该通过
    synchronized
    getter/setter访问。否则,允许Java假设只有一个线程在使用该字段并优化:

    while(!interruptTask){
        // something
    }
    
    进入:


  • 在您的代码中,启动MyTask时没有创建新线程,因此thread.sleep(1000)或interruptTask=true正在执行,因为while循环正在执行,因此您无法中断该循环。

    @Boristeider循环不在问题中,我添加它是为了表示耗时的任务。我将编辑这个问题。我认为这里更大的问题是
    中断任务
    上的竞争条件。这个字段是非易失性的,可以从多个未同步的线程访问。好吧,Java中的
    线程
    只有在合作时才能停止。你的任务必须是可中断的。您需要将任务拆分为多个块,并在处理之间选中一个标志。最好不要使用您自己的标志,而是使用已经存在的。@Banthar我同意interrupttask正在多线程非同步中使用。但我真的无法想象让它同步会做什么?我是说这里的比赛条件是什么意思?@Dude请帮自己一个忙,用Java阅读一下。这里有种族危险。这就是为什么我说应该使用中断API。但是,如果您不知道原子性/可见性,我强烈建议您在执行任何线程之前阅读!OP改变了这个问题。这个答案不再相关。“while(true)”循环将无限期地循环,永远不会退出@以前是的。这就是杜德节目中发生的事情。Java认为,
    interruptTask
    永远不会更改,并将while循环优化为if+无限循环。假设
    interruptTask
    没有从其他线程写入,这是一个有效的优化。不幸的是,Java无法判断这个假设是错误的。@Banthar不完全正确-这是一个过于简单化的假设。JVM将
    interruptTask
    的值缓存在线程的本地缓存中。然后线程将看不到变量的更新值。但是剩下的是+1。这仍然不起作用。“结束”已打印,但背景任务从未完成。
    if(!interruptTask){
        while(true){
            // something
        }
    }
    
    public class Job {
    
       static boolean interruptTask = false;
    
       private static class Mytask extends Thread{
          @Override
          public void run() {
             while(!interruptTask){
                //do some time consuming thing until interruption like looping over millions of times
             }
          }
       }
    
       public static void main(String[] args) throws InterruptedException {
          (new Mytask()).start();
          Thread.sleep(1000);
          interruptTask=true;
          System.out.println("end");
       }
    }