2016-12-15 35 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

相關問題