2010-04-26 5 views
7

Halen çalışmakta olduğum bir vakıf var ve bu yüzden her zaman işleri gerçekleştirmenin daha iyi yollarının farkında olmaya çalışıyorum. Son zamanlarda programın ana iş parçacığı, bazı işlemleri gerçekleştirecek ve daha sonra bittiğini söylemek için kaydı güncelleştirmek için "görev" konuları (her bir db "görev" kaydı için) üreteceği iş için bir program yazmak zorunda kaldım. Bu nedenle, ThreadedTask nesnelerine veya içinde bulunan bir veritabanı bağlantı nesnesine ve PreparedStatement nesnelerine ihtiyacım vardı.Java'da bir Thread'deki PreparedStatements'ın bu kullanımı doğru mu?

Bu, yazım bittiğimde kabaca her atık için PreparedStatement nesnesi oluşturuyor? Ben

Konuyu güvenli mi ..

 
Thread A stmt.setInt(); 
Thread B stmt.setInt(); 
Thread A stmt.execute(); 
Thread B stmt.execute(); 

A's versiyonu execed geçmez ... yarış koşulları yaratabilecek PreparedStatments statik düşünce? Her zaman aynı büyük bir atık değil PreparedStatement nesneleri oluşturma ve yok eder mi?

public class ThreadedTask implements runnable { 
    private final PreparedStatement taskCompleteStmt; 

    public ThreadedTask() { 
     //... 
     taskCompleteStmt = Main.db.prepareStatement(...); 
    } 

    public run() { 
     //... 
     taskCompleteStmt.executeUpdate(); 
    } 
} 

public class Main { 
    public static final db = DriverManager.getConnection(...); 
} 
+2

Bağlantıyı saklamayın, Bağlantınızı gerektiğinde alın. Eğer bettr performansına ihtiyacınız varsa, bir bağlantı havuzu kullanın. AS Thilo, aşağıda, Konular arasında hiçbir şey paylaşmıyor. –

cevap

16

Veri tabanı bağlantılarını (ve hazırlanmış ifadeleri) iş parçacıkları arasında paylaşmanın iyi bir fikir olmadığını düşünüyorum. JDBC, iş parçacığı için güvenli bağlantılar gerektirmez ve çoğu sürücünün olmamasını beklerim.

Her iş parçacığına kendi bağlantısını verin (ya da her sorgu için bağlantıya eşitleyin, ancak bu, muhtemelen birden çok iş parçacığına sahip olma amacını ortadan kaldırır).

Her zaman aynı olan PreparedStatement nesnelerini oluşturmak ve yok etmek büyük bir israf değil midir?

Gerçekten değil. İşin çoğu sunucuda gerçekleşir ve aynı SQL deyimini kullanırsanız önbelleğe alınır ve orada yeniden kullanılır. Bazı JDBC sürücüleri de deyim önbelleğe almayı destekler, böylece istemci tarafı deyim tutamacı bile yeniden kullanılabilir.

Birden çok iş parçacığı yerine (veya bunlara ek olarak) değil, toplu sorguları kullanarak önemli ölçüde iyileştirme görebilirsiniz. Sorguyu bir kez hazırlayın ve tek bir büyük toplu işte çok fazla veri için çalıştırın.

3

Bağlantı havuzunu kullanmak ve havuzdan bağlantı isteğinde bulunmak için her bir iletiyi almanız en iyisidir. Elinizdeki bağlantıyı kullanarak ifadelerinizi oluşturun, kapatmayı unutmayın ve işiniz bittiğinde havuza geri verin. Havuz kullanmanın yararı, iş parçacığı eşzamanlılığının bir sorun haline gelmesi durumunda mevcut bağlantı sayısını kolayca artırabilmenizdir.

6

Threadfilety burada sorun değil. Hepsi sözdizimsel ve işlevsel olarak iyi görünüyor ve yaklaşık yarım saat çalışmalı. Bununla birlikte, kaynakların sızdırılması gerçek sorun. Uygulama yaklaşık yarım saat sonra çökecektir, çünkü bunları kullanıldıktan sonra asla kapatmazsınız. Veri tabanı, daha sonra bağlantıyı kendiliğinden geri alacaktır.

Bu, hazırlıklar önbelleğe alma hakkında endişelenmenize gerek yok dedi. JDBC sürücüsü ve DB bu görevle ilgilenecek. Kaynak sızıntısı konusunda endişe edin ve JDBC kodunuzu olabildiğince sağlam hale getirin.

public class ThreadedTask implements runnable { 
    public run() { 
     Connection connection = null; 
     Statement statement = null; 
     try { 
      connection = DriverManager.getConnection(url); 
      statement = connection.prepareStatement(sql); 
      // ... 
     } catch (SQLException e) { 
      // Handle? 
     } finally { 
      if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {} 
      if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {} 
     } 
    } 
} 

Eğer JDBC kodu yazmak nasıl bir yol değiştirebilir anlamına gelmez bu arada c3p0 (böyle bir bağlantı havuzunu kullanabilir, performansı bağlayan yükseltmek; daima kazanmak ve kaynakların kapatmak mümkün olan en kısa kapsamtry-finally blokta).

+1

Tüm try/catching ile ilgilenen hafif bir sarıcı için Apache Commons DBUtils'e bakın. – Thilo

+0

Ayrıca JPA'yı da kullanabiliriz. Daha uygun olamaz. – BalusC

+0

Java 7+ kullanıyorsanız: "Kaynak bloklarıyla deneyin" seçeneğini kullanın. Bu durumda bağlantıyı ve ifadeyi kapatmayı unutamazsınız. –