java - Java 中的同步数据库访问

标签 java mysql multithreading jdbc synchronization

我有一个数据库,其中包含要发送的电子邮件。我使用多个线程来发送这些电子邮件。我使用的方法是每个线程都会查询数据库,在内存中获取 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
  }
}

关于java - Java 中的同步数据库访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30246578/

相关文章:

java - 从HIVE表中复制副本,需要写出删除的记录并获取计数

php - 在 MySQL 中按列统计变量

c - c中的局部静态变量线程如何不安全?

c++ - lua_newstate 与 lua_newthread

java - 当前线程结束后启动线程

java - 轴客户端 stub 超时问题

java - JBoss 7.1 如何添加模块

mysql - 在注册表中找到 MySQL 的通用路径,因为它在注册表中创建特定于版本的条目作为键

mysql - 这可以在单个 SQL 查询中完成吗?

java - 类似OSGI/Eclipse扩展点的Spring机制