Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 即使在取消ScheduledFuture后,ThreadPoolExecutor也会运行_Java_Multithreading - Fatal编程技术网

Java 即使在取消ScheduledFuture后,ThreadPoolExecutor也会运行

Java 即使在取消ScheduledFuture后,ThreadPoolExecutor也会运行,java,multithreading,Java,Multithreading,我希望创建一个池大小未知的ScheduledThreadPoolExecutor。池大小在运行时确定,可能在1-5之间,在本例中,我使用了大小2。我们使用一个自定义任务,它只是偶尔执行一个方法,但该方法最终会抛出一个异常(我用一个简单的numTimes变量和if语句模拟了这个异常)。如果抛出异常,我只想取消该特定线程的执行!如果取消了所有线程,我想关闭ScheduledThreadPoolExecutor。一旦numTimes==5,我模拟异常以取消线程),我可以通过多种方式取消线程,但它们感觉

我希望创建一个池大小未知的ScheduledThreadPoolExecutor。池大小在运行时确定,可能在1-5之间,在本例中,我使用了大小2。我们使用一个自定义任务,它只是偶尔执行一个方法,但该方法最终会抛出一个异常(我用一个简单的numTimes变量和if语句模拟了这个异常)。如果抛出异常,我只想取消该特定线程的执行!如果取消了所有线程,我想关闭ScheduledThreadPoolExecutor。一旦numTimes==5,我模拟异常以取消线程),我可以通过多种方式取消线程,但它们感觉不太对劲

作为旁注,我把ScheduledFuture放在了所有地方,只是想随便取消它

    public class Test 
{
  static ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(2);

  public static void main(String[] args) 
  { stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 1000, TimeUnit.MILLISECONDS);
    stpe.scheduleWithFixedDelay(new UpdateTask(2), 0, 5000, TimeUnit.MILLISECONDS);
//    stpe.shutdown();
  }

  public static class UpdateTask implements Runnable
  {  
     int id;
     int numTimes = 0;
     ScheduledFuture<?> t;

     public UpdateTask(int id)
     { this.id = id;
     }

     public void run()
     { System.out.println("Hello " + id + " num: " + numTimes);
       String fn = "C:\\lib" + id;
       if (numTimes++ == 5)
       { File f = new File(fn);
         f.mkdir();
         t.cancel(false);
       }
     }
  }
}
公共类测试
{
静态ScheduledThreadPoolExecutor stpe=新ScheduledThreadPoolExecutor(2);
公共静态void main(字符串[]args)
{stpe.scheduleWithFixedDelay(新的更新任务(1),0,1000,时间单位为毫秒);
stpe.scheduleWithFixedDelay(新的更新任务(2),0,5000,时间单位为毫秒);
//stpe.shutdown();
}
公共静态类UpdateTask实现可运行
{  
int-id;
int numTimes=0;
计划未来t;
公共更新任务(int-id)
{this.id=id;
}
公开募捐
{System.out.println(“Hello”+id+“num:+numTimes”);
字符串fn=“C:\\lib”+id;
如果(numTimes++==5)
{File f=新文件(fn);
f、 mkdir();
t、 取消(假);
}
}
}
}
从run()或main()调用t.cancel()具有相同的效果,即线程停止执行,但程序不停止运行。当然,这是因为ThreadPoolExecutor仍然在做一些事情,尽管两个线程不再被调度

我尝试在stpe上调用shutdown,但它没有完成线程执行。创建了两个目录,并注释掉了stpe.shutdown,而不是其他目录

我想不出一个优雅的方法来取消ScheduledFuture,然后在取消所有ScheduledFuture时取消ScheduledThreadPoolExecutor。

最后进近## 我无法让s1.get()按照下面的答案工作,所以我只是创建了自己的类来处理它

public class Test 
{
  static ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(2);
  static CancelUpdateTasks canceller;

  public static void main(String[] args) 
  { Test t = new Test();
    canceller.add(0, stpe.scheduleWithFixedDelay(new UpdateTask(0), 0, 1000, TimeUnit.MILLISECONDS));
    canceller.add(1, stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 5000, TimeUnit.MILLISECONDS));
    canceller.waitForSchedules();
    stpe.shutdown();
  }

  public Test() 
  { canceller = new CancelUpdateTasks();
  }

  public static class UpdateTask implements Runnable
  {  
     int id;
     int numTimes = 0;

     public UpdateTask(int id)
     { this.id = id;
     }

     public void run()
     { System.out.println("Hello " + id + " num: " + numTimes);
       if (numTimes++ == 5)
       { canceller.cancel(id);
       }
     }
  }

  public class CancelUpdateTasks 
  { List<ScheduledFuture<?>> scheduler;
    boolean isScheduled;

    public CancelUpdateTasks() 
    { scheduler = new ArrayList<ScheduledFuture<?>>();
      isScheduled = false;
    }

    public void waitForSchedules() 
    { int schedId = 0;
      while(isScheduled)
      { ScheduledFuture<?> schedule = scheduler.get(schedId);
        if (schedule.isCancelled())
        { if (schedId == scheduler.size() - 1)
            return;
          schedId++;
        }
        else
        { try 
          { Thread.sleep(1000);
          } 
          catch (InterruptedException e) 
          { e.printStackTrace();
          }
        }
      }
    }

    public void add(int id, ScheduledFuture<?> schedule) 
    { scheduler.add(id, schedule);
      if (!isScheduled)
        isScheduled = true;
    }

    public void cancel(int id)
    { scheduler.get(id).cancel(false);
    }

    public void cancelNow(int id)
    { scheduler.get(id).cancel(true);
    }
  }
}
公共类测试
{
静态ScheduledThreadPoolExecutor stpe=新ScheduledThreadPoolExecutor(2);
静态CancelUpdateTasks消除器;
公共静态void main(字符串[]args)
{Test t=new Test();
add(0,stpe.scheduleWithFixedDelay(新的UpdateTask(0),0,1000,TimeUnit.ms));
add(1,stpe.scheduleWithFixedDelay(新的UpdateTask(1),0,5000,TimeUnit.ms));
canceller.waitForSchedules();
stpe.shutdown();
}
公开考试()
{canceller=new CancelUpdateTasks();
}
公共静态类UpdateTask实现可运行
{  
int-id;
int numTimes=0;
公共更新任务(int-id)
{this.id=id;
}
公开募捐
{System.out.println(“Hello”+id+“num:+numTimes”);
如果(numTimes++==5)
{canceler.cancel(id);
}
}
}
公共类CancelUpdateTasks
{List>();
isScheduled=false;
}
公共计划表()
{int schedId=0;
while(按计划)
{ScheduledFuture schedule=scheduler.get(scheddid);
if(schedule.isCancelled())
{if(schedId==scheduler.size()-1)
返回;
schedId++;
}
其他的
{试试看
{线程睡眠(1000);
} 
捕捉(中断异常e)
{e.printStackTrace();
}
}
}
}
public void add(int id,ScheduledFuture schedule)
{scheduler.add(id,schedule);
如果(!isScheduled)
isScheduled=true;
}
公共作废取消(int id)
{scheduler.get(id).cancel(false);
}
立即取消公共无效(int id)
{scheduler.get(id).cancel(true);
}
}
}

您需要对池发出关机命令。JVM将继续运行,直到只有守护进程线程处于活动状态。默认情况下,ThreadPoolExecutor将创建非守护进程线程

只需调用
stpe.shutdown()


编辑:基于OPs更新

shutdown
无可否认,ScheduledThreadPoolExecutor与普通ThreadPoolExecutor不同。在这种情况下,
shutdown
可防止任何计划任务被重新计划。要使其正常工作,您必须等待期货交易完成。您可以通过在
ScheduledFuture

ScheduledFuture sf1 = stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 1000, TimeUnit.MILLISECONDS);
ScheduledFuture sf2 = stpe.scheduleWithFixedDelay(new UpdateTask(2), 0, 5000, TimeUnit.MILLISECONDS);
sf1.get();
sf2.get();
stpe.shutdown();

在这种情况下,两个任务都是异步运行的,主线程将首先等待sf1完成,然后等待sf2完成,最后关闭

您将要对池发出关机命令。JVM将继续运行,直到只有守护进程线程处于活动状态。默认情况下,ThreadPoolExecutor将创建非守护进程线程

只需调用
stpe.shutdown()


编辑:基于OPs更新

shutdown
无可否认,ScheduledThreadPoolExecutor与普通ThreadPoolExecutor不同。在这种情况下,
shutdown
可防止任何计划任务被重新计划。要使其正常工作,您必须等待期货交易完成。您可以通过在
ScheduledFuture

ScheduledFuture sf1 = stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 1000, TimeUnit.MILLISECONDS);
ScheduledFuture sf2 = stpe.scheduleWithFixedDelay(new UpdateTask(2), 0, 5000, TimeUnit.MILLISECONDS);
sf1.get();
sf2.get();
stpe.shutdown();

在这种情况下,两个任务都是异步运行的,主线程将首先等待sf1完成,然后等待sf2完成,最后关闭

+1您几乎总是希望调用
stpe.shutdown()将所有任务提交给
执行器服务后。在本例中,在
main()
的末尾