2016-12-15 59 views
0

我有一个特例,如下所示。 我有Listener类和Uploader类。 Listener类通过网络监听消息,处理它们并从中创建另一个小对象。有一个有状态的辅助类是不好的做法吗?

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(); 
    } 
} 

}

上传器类需要经由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

您可以通过使用专用静态ThreadLocal来组合上述两种方法来保存上传器。

纵观大局:

我觉得你的同事有一个有效点。考虑到上传器可能位于单独的线程或线程池中。这可以全部从Listener中抽象出来并隐藏起来。然后,上传器可以根据元素数量或者是否已经设置毫秒数而不接收更多元素来决定是否有足够的工作。也许允许Listener刷新/结束,但不应该 - 这种要求对其他编码人员来说是一个难题。

+0

如果我没有错,在这种情况下,我将不得不维护共享的对象列表,上传者线程可以定期监视和上传对象。你是在提议吗? – Kartik

+0

@Kartik这是一个可能的实现。或者每个监听器线程都可以有一个关联的上传器线程。我的观点是听众应该完全透明 –

+0

这实际上是有道理的。但即使在这种情况下,它的上传者必须维持分区状态的权利? – Kartik

0

我想你以一种错误的方式提出这个问题。你问这是否是一种不好的做法。

想想另一种方式。实际上你正在解决的任务是什么?这个任务是否有意义?你的实施是否好?

您正在解决的任务是将几个对象“打包”在一起进行上传,而不是逐个上传。

这可能完全有意义减少上传次数。但也许不是,这取决于单个上传成本的多少开销。我什么都不知道,可能是完全有道理的。

现在,您的执行情况良好吗?那么...

首先你已经提到了多个线程,所以你需要格外小心地在你的对象列表上进行同步。

接下来,等待PARTITION_SIZE好吗?如果你只有PARTITION_SIZE - 1对象呢?你可以永远等待最后一个,而不是发送其他对象。

最后,如果您的应用程序停机,会发生什么?您将失去已发布到上传队列但尚未发送的数据。这可能真的很糟糕。该解决方案不可靠。

+0

1.如果对象数量少于PARTITION_SIZE – Kartik

+0

,我最终会调用完成方法以提供上传机会。是否有保证在何时终止?将被调用? – lexicore

+0

1.就像我提到的,上传对象只能用在1个线程内。那是这个班级的合同,我在这个问题上提到过两次。 2.如果对象数量少于PARTITION_SIZE 3.我有一个结束方法在结束时调用,以提供上传的机会3.是的,这可能发生,我们有我们的方法重试超出范围给定的类。并且可以再次获取要上传的数据。所以这真的不是我们的关注 说了这么多,这里的问题是更多关于使用静态方法vs上传对象 – Kartik