我有一个特例,如下图所示。 我有一个Listener类和一个Uploader类。侦听器类通过网络侦听消息,处理它们并从中创建另一个小对象。
public class Listener {
Uploader uploader;
Listener(String location) {
uploader = new Uploader(location);
}
public void listen(Message msg) {
ProcessedObject obj = process(msg);
uploader.add(obj);
}
public void terminate() {
if (null != uploader) {
uploader.finish();
}
}
}
Uploader类通过add方法获取一个对象,并决定何时上传。为此,它维护一个列表。它还具有位置字符串,该字符串特定于一个侦听器。这是要点:
/**
* This class is not thread safe, and an object should not be shared across threads
*
*/
public class Uploader {
String location;
List<ProcessedObject> objects;
Uploader(String location) {
this.location = location;
}
void add(ProcessedObject obj) {
objects.add(obj);
if (objects.size() > PARTITION_SIZE) {
uploadObjects(objects);
objects.clear();
}
}
void finish() {
uploadObjects(objects);
}
}
因此,如果对象数大于PARTITION_SIZE,则上传。应用程序中有多个侦听器,每个侦听器都在一个单独的线程上运行。每个监听器都有自己的上传器对象。我已经清楚地提到过这个类在javadoc中不是线程安全的。
现在我的问题是,这是一个好习惯吗?
我的一些同事说这不是一个好习惯,建议使用静态方法上传,而不是创建上传者的实例。但我的论点是,这将使我的监听器类变得混乱(因为那时监听器必须保持计数,并在终止剩余对象之前再次检查并上传)
通过我的方法,整个分区和上传逻辑在上传器类中可用,因此它提高了可读性和可维护性。
我的问题是,我的方法是不好的做法(考虑到我特别指出上传者并不意味着线程安全)?
此外,我在这里尝试做什么设计模式?如果是,哪一个?
编辑:我接受我没有正确构建问题。我不关心分区或上传。关于为每个线程创建一个Uploader类对象的方法,与使用静态方法创建无状态Uploader类来完成这项工作。
我是否上传剩余的对象,或者我是否应该进行分区,不是这个问题的关注点。
答案 0 :(得分:0)
您可以使用私有静态ThreadLocal来合并这两种方法来保存上传器。
从更大的角度看:
我认为你的同事有一个有效的观点。考虑到Uploader可以位于单独的线程或线程池中。这些都可以从Listener中抽象出来并隐藏起来。然后上传者可以根据元素的数量决定它是否有足够的工作,或者它是否已经设置了毫秒的持续时间而没有接收到更多的元素。也许允许倾听者冲洗/完成,但它不应该 - 那种要求对其他程序员来说是一个难题。
答案 1 :(得分:0)
我认为你以错误的方式提出这个问题。你问这是不是一种坏习惯。
反过来思考。你正在解决的任务是什么?这项任务有意义吗?你的实施是否很好?
您正在解决的任务是&#34;包装&#34;一些对象一起上传,而不是逐个上传。
减少上传次数可能完全有意义。但也许不是,这取决于单个上传成本的开销。不知道我的假设是它可能完全有意义。
现在,您的实施是否良好?嗯......
首先,您提到了多个线程,因此您需要特别注意在对象列表上进行同步。
接下来,等待PARTITION_SIZE
是否合适?如果你只有PARTITION_SIZE - 1
个对象怎么办?你可以永远等待最后一个,而不是发送其他对象。
最后,如果您的应用程序出现故障会怎样?您将丢失已发布到上传队列但尚未发送的数据。这可能真的很糟糕。这个解决方案不可靠。