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