这是每日编码问题中的一个问题。我已经用Java实现了它。对于函数f,我使用了Runnable接口。
问题:
这个问题是苹果公司提出的。
实现一个作业调度程序,它接受函数f和整数n,并在n毫秒之后调用f。
解决方案:
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);
}
}
```发布于 2021-07-26 10:02:53
首先,您已经掌握了基本知识,即命名约定、缩进和一个相当合理的OOP结构。但你要求审查,所以我来了。
您可能了解Timer类,完全了解您实现的内容。
所以我想,你的节目是作为一个练习。
你的课名叫Ideone,这太糟糕了。你没有创造出一种IDE。如果您的环境以某种方式强制使用这个类名,请尽可能快地离开这个类名。
使用正确的包名。将代码放入未命名的(顶级)包是个坏主意,因为它会引发与他人的名称冲突。
void schedule(final Runnable f, int n);单字母变量名称对它们的含义没有任何说明。一个更好的名字是
void schedule(final Runnable job, int millisecondsFromNow);对于等待并在以后执行函数的线程,您将使用变量名称job,我将将其称为jobExecutionThread。
import java.util.*;从长远来看,这可能会造成问题。假设Java管理员在将来的某个版本中将一个新类包含到java.util包中,一个与您引用的其他类名发生冲突的类。其结果可能是您的代码将不再使用这个未来的Java版本进行编译。
通过让IDE为您管理导入,您可以很容易地避免这种情况(如果有必要,还可以在IDE设置中禁止任何通配符导入)。
JobScheduler在类JobScheduler中创建一个内部接口Ideone,这样就没用了。
如果您希望允许更多的JobScheduler实现(尽管我没有看到其中的意义),那么将它移到顶层。
对于当前的使用,就在只有一个实现的顶级类Ideone中,我只需使用实现类,并去掉接口。
您在使用合成整数id命名作业和维护作业映射方面投入了大量精力。干什么用?For what?
中只使用id
jobs.remove(id);为了从集合中删除对象,您不需要这个整数,只需维护一个集合并删除线程本身
private final Collection<Thread> jobs = ...;
jobs.remove(this);但为什么要保持这样的收藏呢?目前,你对它什么都不做。如果您有一个信息调用,返回一个待定作业列表或诸如此类的事情,这将是有意义的。但只要这不存在,就扔掉那些工作管理方面的东西。
关于整数ids,一般情况下:对我来说,这是从远古时代遗留下来的,当时机器识别对象的唯一方法被认为是通过编号。首先,对象有自己的标识(在equals()和hashCode()方法支持的Java中,如果必要的话),如果需要额外的东西,使用数字通常会产生比需要的更多的问题。例如,看互联网。没有人会尝试使用整数作为web资源标识,URL字符串做得更好。
养成记录代码的重要方面的习惯,特别是接口、类和公共方法。你的团队同事(以及一年后你未来的自我)会很感激的。这些注释遵循Javadoc风格,因为IDE和其他工具都很支持它。
https://codereview.stackexchange.com/questions/264387
复制相似问题