2015-07-07 19 views
5

Büyük dosyaları indirdiğim, bunları çözümlediğim ve daha sonra dosyadan aldığım verileri başka bir dosyaya yazdığım bir program çalıştırıyorum.Bir "Zincirler Zinciri" bu Java uygulaması için kötü bir çözüm mü?

Dosyaların indirilmesi ve ayrıştırılması uzun zaman alır, ancak yazma görevi yalnızca bir dakika kadar sürer. Beraber attığım çözümüm, üç parçanın üç sabit yüzdesine sahip olmaktı.

ExecutorService downloadExecutor = Executors.newFixedThreadPool(3); 
ExecutorService parseExecutor = Executors.newFixedThreadPool(3); 
ExecutorService writeExecutor = Executors.newFixedThreadPool(3); 

indirme havuzunda bir iş parçacığı sonra bir parametre olarak dosya adına sahip, çözümleyici threadpool için yeni bir iş parçacığı gönderir dosya indirir. Bu iş parçacığı içinde yapılır. İndirme iş parçacığı daha sonra dosya URL'lerinin listesinden başka bir dosyayı indirmeye çalışır.

Ayrıştırıcı iş parçacığı, dosyadan istediğim verileri ayrıştırmayı bitirdikten sonra, daha sonra bir .csv dosyasına yazıldığı yazma iş parçacığına verileri içeren yeni bir iş parçacığı gönderir.

Sorum şu, bunun için daha zarif bir çözüm varsa. Gerçekten çok karmaşık bir iş parçacığı yapmadım. İndirmek ve ayrıştırmak için çok fazla dosyam olduğundan, herhangi bir zamanda iş parçacığının boşta kalmasını istemiyorum. Bir kez daha, bir dosya ayrıştırmak biraz zaman alabilir, bu yüzden ilk önce bu dosyaları indirmek için ayrılmış ayrı konuları yapmak olabilir.

cevap

8

Neden sadece bir tane iş parçacığı havuzu kullanmıyorsunuz? Karşıdan yükleme, ayrıştırma ve kaydetme birbirleri için beklemeli, böylece görevlerin en iyi şekilde ayrılması dosya başına bir iş parçacığı kullanmak olacaktır.

+0

Daha önce de belirttiğim gibi, bu dosyalar boyut olarak birkaç GB olabilir. Ayrıştırma işleminin tamamlanması 30 dakikadan bir saat sürebilir. Mantığım, dosyanın yeni bir dosya indirilmeden önce ayrıştırılmasını beklemek yerine, dosyaları indirmeye devam edecek ayrı konuları ayırmak ve aşağı indiğinde bu dosyayı iş parçacığına göndermektir. Bu ayrıştırma bekleyen bir dosya kuyruğu ile sonuçlanacaktır. Bana daha verimli geliyor. – GreenGodot

+0

En basit olanı ilk @GreenGodot yapın. Genel işleminiz yine de en yavaş kısımla sınırlıdır ... gerçekten diskte bekleyen yüzlerce GB dosyasının olmasını ister misiniz? – Dennis

+0

Herhangi bir yardımcı olursa, dosyayı ayrıştırmayı bitirdiğimde, indirilen dosyayı File.delete() kullanarak silerim. uzay problemini tamamen çözmez ama bu yardımcı olur mu? – GreenGodot

2

Bu, birçok geliştiricinin benzer kodlama yaptığı için bu kötü bir uygulama değildir. Ama aklında tutmanız gereken bir şey var.

Bir numara, Daha fazla iş parçacığınız olduğu için performansın artmasını bekleyemezsiniz. İşlemci sayısına göre optimum sayıda iplik bulunmaktadır.

İki numaralı, Özel durumların nasıl ele alındığından emin olmalısınız.

Üç Numara, Uygulamayı durdurmanız gereken bir durumda tüm iş parçacığı havuzlarını kapatabildiğinizden emin olmalısınız.

2

Yani senin sorunun iki yönü vardır:

  1. Compute
  2. IO

okuma ve dosyaya yazma IO bağlı bağlı bağlı. Async IO, IO bağlı görevler için en iyisidir. Java, tamamlama işleyicileri aracılığıyla devam ettirmenin sağlandığı iş parçacığı havuzları hakkında endişelenmeden dosyaları okumanıza ve yazmanıza olanak veren AsynchronousFileChannel'a sahiptir. Complete Example.

AsynchronousFileChannel ch = AsynchronousFileChannel.open(path); 
    final ByteBuffer buf = ByteBuffer.allocate(1024); 
    ch.read(buf, 0, 0, 
      new CompletionHandler() { 
       public void completed(Integer result, Integer length){   
        .. 
       } 

       public void failed(Throwable exc, Integer length) { 
        .. 
       } 
      } 
    ); 

Ve yazma için aynı şeyi, sadece

ch.write(... 

Hayır dosyayı ayrıştırmak için, bir bilgisayar bağlı olan bir görevi şu kanala yazacağınız ve CPU çekirdekleri sıcak almalısınız Bunun için sahip olduğunuz çekirdek sayısına eşit bir iş parçacığı havuzu atayabilirsiniz.

executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) 

Şimdi hatırlamak elde ediyoruz: kodunuzu test etmek gerekir ve eşzamanlı kodu test zordur. Eğer doğruluğunu kanıtlayamıyorsan, yapma.

İlgili konular