首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >日常编码问题:作业调度程序在特定时间后调用函数

日常编码问题:作业调度程序在特定时间后调用函数
EN

Code Review用户
提问于 2021-07-25 17:37:10
回答 1查看 83关注 0票数 1

这是每日编码问题中的一个问题。我已经用Java实现了它。对于函数f,我使用了Runnable接口。

问题:

这个问题是苹果公司提出的。

实现一个作业调度程序,它接受函数f和整数n,并在n毫秒之后调用f

解决方案:

代码语言:javascript
复制
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

class Ideone {

    interface JobScheduler {
        void schedule(final Runnable f, int n);
    }

    static class JobSchedulerImpl implements JobScheduler {
        private final AtomicInteger idValue = new AtomicInteger(0);
        private final Map<Integer, Thread> jobs = new ConcurrentHashMap<>();

        private int getNextId() {
            return idValue.incrementAndGet();
        }

        @Override
        public void schedule(final Runnable f, final int n) throws IllegalArgumentException {
            if (n < 0) {
                throw new IllegalArgumentException("n cannot be nagative");
            }
            int id = getNextId();
            Thread job = new Thread() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(n);
                        f.run();
                        jobs.remove(id);
                    } catch (InterruptedException e) {
                        jobs.remove(id);
                    }
                }
            };
            jobs.put(id, job);
            job.start();
        }
    }

    public static void main(String[] args) {
        JobScheduler jobScheduler = new JobSchedulerImpl();
        jobScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("Job1 launched at: " + System.currentTimeMillis());
            }
        }, 10000);
        jobScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("Job2 launched at: " + System.currentTimeMillis());
            }
        }, 1000);
    }
}
```
代码语言:javascript
复制
EN

回答 1

Code Review用户

发布于 2021-07-26 10:02:53

Basics

首先,您已经掌握了基本知识,即命名约定、缩进和一个相当合理的OOP结构。但你要求审查,所以我来了。

重新发明车轮

您可能了解Timer类,完全了解您实现的内容。

所以我想,你的节目是作为一个练习。

使用专有名称

你的课名叫Ideone,这太糟糕了。你没有创造出一种IDE。如果您的环境以某种方式强制使用这个类名,请尽可能快地离开这个类名。

使用正确的包名。将代码放入未命名的(顶级)包是个坏主意,因为它会引发与他人的名称冲突。

代码语言:javascript
复制
void schedule(final Runnable f, int n);

单字母变量名称对它们的含义没有任何说明。一个更好的名字是

代码语言:javascript
复制
void schedule(final Runnable job, int millisecondsFromNow);

对于等待并在以后执行函数的线程,您将使用变量名称job,我将将其称为jobExecutionThread

不要使用通配符导入

代码语言:javascript
复制
import java.util.*;

从长远来看,这可能会造成问题。假设Java管理员在将来的某个版本中将一个新类包含到java.util包中,一个与您引用的其他类名发生冲突的类。其结果可能是您的代码将不再使用这个未来的Java版本进行编译。

通过让IDE为您管理导入,您可以很容易地避免这种情况(如果有必要,还可以在IDE设置中禁止任何通配符导入)。

接口JobScheduler

在类JobScheduler中创建一个内部接口Ideone,这样就没用了。

如果您希望允许更多的JobScheduler实现(尽管我没有看到其中的意义),那么将它移到顶层。

对于当前的使用,就在只有一个实现的顶级类Ideone中,我只需使用实现类,并去掉接口。

职务管理

您在使用合成整数id命名作业和维护作业映射方面投入了大量精力。干什么用?For what?

中只使用id

代码语言:javascript
复制
jobs.remove(id);

为了从集合中删除对象,您不需要这个整数,只需维护一个集合并删除线程本身

代码语言:javascript
复制
private final Collection<Thread> jobs = ...;

jobs.remove(this);

但为什么要保持这样的收藏呢?目前,你对它什么都不做。如果您有一个信息调用,返回一个待定作业列表或诸如此类的事情,这将是有意义的。但只要这不存在,就扔掉那些工作管理方面的东西。

关于整数ids,一般情况下:对我来说,这是从远古时代遗留下来的,当时机器识别对象的唯一方法被认为是通过编号。首先,对象有自己的标识(在equals()hashCode()方法支持的Java中,如果必要的话),如果需要额外的东西,使用数字通常会产生比需要的更多的问题。例如,看互联网。没有人会尝试使用整数作为web资源标识,URL字符串做得更好。

Javadoc

养成记录代码的重要方面的习惯,特别是接口、类和公共方法。你的团队同事(以及一年后你未来的自我)会很感激的。这些注释遵循Javadoc风格,因为IDE和其他工具都很支持它。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/264387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档