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

Java “真的这么难吗?”;推迟;任务(或“等待空闲”)

Java “真的这么难吗?”;推迟;任务(或“等待空闲”),java,timer,scheduled-tasks,Java,Timer,Scheduled Tasks,如何使用以下属性实现“等待空闲”模型: 当调用方法do()时,在X延迟之后,将调用close()方法 如果在X时间过去之前再次调用do()方法,则对close()的调用必须推迟 示例 场景1:(对于超时=10秒): 用户在时间0调用do() 在时间10时,调用close()方法,因为用户没有再次调用do() 场景2:(同时超时=10秒): 用户在时间0调用do()。(因此在10中,应该调用close()方法) 在8时,用户再次调用do() 在10时,由于close()延迟了10秒,因此没有发

如何使用以下属性实现“等待空闲”模型:

  • 当调用方法
    do()
    时,在X延迟之后,将调用
    close()
    方法
  • 如果在X时间过去之前再次调用
    do()
    方法,则对
    close()
    的调用必须推迟
示例

场景1:(对于超时=10秒):

  • 用户在时间
    0
    调用
    do()
  • 在时间
    10
    时,调用
    close()
    方法,因为用户没有再次调用
    do()
  • 场景2:(同时超时=10秒):

  • 用户在时间
    0
    调用
    do()。(因此在
    10
    中,应该调用
    close()
    方法)
  • 8
    时,用户再次调用
    do()
  • 10
    时,由于
    close()
    延迟了10秒,因此没有发生任何事情
  • 在时间
    18
    时,调用
    close()
    方法,因为自
    8
    以来,用户没有再次调用
    do()
  • 我所尝试的:

    这个代码很难看。 它也非常低效且占用内存,因为
    do()
    函数每秒被调用大约50次


    我应该怎么做才能使它高效、整洁地工作?(这真的很难吗?

    你走的路是对的,不是很难

    这是我想给你的建议。只创建一次计时器。让它成为班级的一员。在构造函数中创建其实例

    当方法被调用时,按您现在所做的方式创建任务。但是,您可以创建单独的类,甚至可以提前创建它的实例,当调用
    do()
    方法时,只需对其进行调度,因此将根据您的调度调用
    close()

    调用
    do()
    时,取消先前创建的关闭任务。这将确保在再次调用方法
    do()
    时不会关闭任何内容


    顺便说一句,因为在java中,
    do
    是一个保留字,所以不能用这种方式调用该方法。这意味着您的代码甚至无法编译。更改名称。

    在打开()时设置10秒计时器任务。

    保留一个变量
    long lastCall
    ,该变量从
    doIt()

    在时间任务正文中,检查
    lastCall
    是否在10秒内。如果是,请重新安排计时器任务的剩余时间。如果没有,请调用
    close()


    当您从
    lastCall

    读写时,请不要忘记对某些内容进行
    同步
    ,我找到了一个合适的解决方案:

    public class TimerExample {
    
        private TimerTask tt;
        ScheduledFuture<?> future;
        private ScheduledThreadPoolExecutor s;
    
        public TimerExample() {
            s = new ScheduledThreadPoolExecutor(1);
            tt = new TimerTask() {
    
                @Override
                public void run() {
                    close();
                }
            };
            doSomething();
        }
    
        public void doSomething() {
            if (future != null) future.cancel(true);
            future = s.schedule(tt, 3000, TimeUnit.MILLISECONDS);
            System.out.println("do");
        }
    
        public void close() {
            System.out.println("Close");
        }
    
    }
    
    公共类TimerExample{
    专用定时器任务tt;
    计划未来;
    私有调度线程池执行器;
    公共TimerExample(){
    s=新的ScheduledThreadPoolExecutor(1);
    tt=新时间任务(){
    @凌驾
    公开募捐{
    close();
    }
    };
    doSomething();
    }
    公共无效剂量测定法(){
    如果(future!=null)future.cancel(true);
    future=s.schedule(tt,3000,时间单位毫秒);
    System.out.println(“do”);
    }
    公众假期结束(){
    系统输出打印项次(“关闭”);
    }
    }
    
    为什么要一次又一次地创建
    计时器?您应该重复使用一个计时器,并且只取消/安排其上的任务。当你解决这个问题时,就不会有任何低效和内存消耗了。
    线程“main”java.lang.IllegalStateException中的异常:任务已经调度或取消了
    @MarkoTopolnik-你不能在已经取消的计时器上调度任务。@Perception当然。这就是为什么你不取消计时器。您取消了任务。@MarkoTopolnik-没关系,我知道您在哪里陈述了任务与计时器。我明白了,但是我不完全理解第三段,我应该在do()方法中做什么(以及在单独的类中做什么)?(命名只是因为我直接编写了代码,没有考虑到这一点)。
    public class TimerExample {
    
        private TimerTask tt;
        ScheduledFuture<?> future;
        private ScheduledThreadPoolExecutor s;
    
        public TimerExample() {
            s = new ScheduledThreadPoolExecutor(1);
            tt = new TimerTask() {
    
                @Override
                public void run() {
                    close();
                }
            };
            doSomething();
        }
    
        public void doSomething() {
            if (future != null) future.cancel(true);
            future = s.schedule(tt, 3000, TimeUnit.MILLISECONDS);
            System.out.println("do");
        }
    
        public void close() {
            System.out.println("Close");
        }
    
    }