[英]Synchronized DB Access in Java
我有一個數據庫,其中包含要發送的電子郵件。 我正在使用多個線程來發送這些電子郵件。 我使用的方法是每個線程將查詢數據庫,在內存中獲取N封電子郵件並將其標記為已發送。 另一個線程將看到標記為的這N封電子郵件,然后繼續並獲取下N項。
現在,此方法不起作用,之前線程1可以更新發送的條目,線程2查詢電子郵件,因此兩個線程最終都收到相同的電子郵件集。
每個線程都有自己的數據庫連接。 這是這種行為的根本原因嗎? 我是否應該在所有線程之間共享一個連接對象? 還是我可以使用更好的方法?
我的建議是讓一個線程負責查詢數據庫,將檢索到的電子郵件放在線程安全的隊列中(例如ArrayBlockingQueue ,它具有被綁定的優勢); 然后,您可以有任意數量的線程從此隊列中刪除和處理電子郵件。 ArrayBlockingQueue
上的同步開銷非常輕巧,因此您無需使用數據庫事務或類似的東西。
class EmailChunk {
Email[] emails;
}
// only instantiate one of these
class DatabaseThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public DatabaseThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
EmailChunk newChunk = // query database, create email chunk
// add newChunk to queue, wait 30 seconds if it's full
emailQueue.offer(newChunk, 30, TimeUnit.SECONDS);
}
}
// instantiate as many of these as makes sense
class EmailThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public EmailThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
// take next chunk from queue, wait 30 seconds if queue is empty
emailChunk nextChunk = emailQueue.poll(30, TimeUnit.SECONDS);
}
}
class Main {
final int queueSize = 5;
public static void main(String[] args) {
BlockingQueue<EmailChunk> emailQueue = new ArrayBlockingQueue<>(queueSize);
// instantiate DatabaseThread and EmailThread objects with this queue
}
}
您需要一種方法來共享一個方法//以控制並發。 整理語句以獲取電子郵件並標記它們。 然后發送電子郵件。 像這樣:
public void processMails(){
List<String> mails;
synchronized(this){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
此方法可以在您的DAO Facade中,所有線程都可以訪問。
編輯:
如果您有DAO類的多個實例:
public void processMails(){
List<String> mails;
synchronize(DAO.class){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
其他選擇
private static final Object LOCK = new Object();
public void processMails(){
List<String> mails;
synchronize(LOCK){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.