在这里,我有线程池和另一个轮询类,用于实现轮询和从数据库读取消息。现在的问题是,由于有大量消息在等待,因此我必须避免读取冗余消息以进行更新和处理其他正在等待的消息。

// the code for poll method
public void poll() throws Exception {
    // Method which defines polling of the data entry for counting its size.
    st = conn.createStatement();
    int count = 1;
    long waitInMillisec = 1 * 60 * 125; // Wait for 7.5 seconds.
    for (int i = 0; i < count; i++) {
        System.out.println("Wait for " + waitInMillisec + " millisec");
        Thread.sleep(waitInMillisec);

        java.util.Date date = new java.util.Date();
        Timestamp start = new Timestamp(date.getTime());
        rs = st.executeQuery("select * from msg_new_to_bde where ACTION=804");
        java.util.Date date1 = new java.util.Date();
        Timestamp end = new Timestamp(date1.getTime());
        System.out.print("Query count: ");
        System.out.println(end.getTime() - start.getTime());

        Collection<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
        while (rs.next()) {
            KpiMessage filedClass = convertRecordsetToPojo(rs);
            pojoCol.add(filedClass);

        }

最佳答案

我不知道您是否可以选择如何存储消息,但是它们似乎已插入要轮询的表中。您可以将数据库触发器添加到该表,该触发器又将消息推入具有相同数据和相关ID的Oracle AQ中。

如果您可以不用该表,那么建议您仅在同一模式中定义Oracle AQ来存储消息,并使用模式匹配(如corrid =“ 804%”)按部分相关ID出队。 AQ消息的完整相关ID可能是“ 804” +消息的唯一pk。然后,您可以将该同一个队列重用于多个动作,例如,定义Java队列804动作工作者类,以等待该特定动作的消息(AQ消息上的804相关ID前缀)。

Oracle AQ的文档非常不错,用于创建队列的软件包是dbms_aqadm。用于入队/出队的软件包是dbms_aq。在创建aq和使用dbms_aq软件包之前,您还需要获得一些特权/特权。 dbms_aq应该可以从Java轻松调用。

转到docs.oracle.com查找有关dbms_aqadm和dbms_aq软件包的详细信息。一旦创建了AQ(将创建一个支持队列的AQ表),我建议您在corrid上向AQ表添加索引以提高性能。

如果您无法避免使用现有的表体系结构,或者不想使用AQ技术,则可以使用的另一种方法是在Oracle(dbms_lock软件包)中创建一个锁,然后在轮询类中将其调用为获取锁定或阻止/等待。这样,您可以同步所有轮询类,以避免多个线程接收相同的消息。因此,轮询类要做的第一件事就是尝试获取锁,如果成功,它将从表中拉出一条消息,对其进行处理,并在处理后对其进行更新,然后释放该锁。 dbms_lock软件包可以阻止/等待锁定,也可以立即返回,但是根据操作成功/失败,您可以采取进一步的措施。但这将帮助您控制线程,避免拾取相同的消息。 Oracle的文档在此软件包上也相当出色。

08-07 05:35