【问题标题】:How to achieve asynchronous processing如何实现异步处理
【发布时间】:2013-01-07 09:06:51
【问题描述】:

我想在我的 Java 程序中传递一条异步消息,所以第一步它应该持续监控数据库中某些表的变化。当有新的传入消息时,它应该显示它。只要应用程序正在运行,这应该是重复的过程。

我可以知道如何处理以下代码,其中包含轮询方法,它必须每 6 秒无限地调用自身,并且还应该在数据库中找到新的传入消息。

这里是sn-p的代码:

public class PollingSynchronizer implements Runnable {

private Collection<KPIMessage> incomingMessages;
private Connection dbConnection;


/**
 * Constructor. Requires to provide a reference to the KA message queue
 * 
 * @param incomingMessages reference to message queue
 * 
 */
   public PollingSynchronizer(Collection<KpiMessage> incomingMessages, Connection dbConnection) {
    super();
    this.incomingMessages = incomingMessages;
    this.dbConnection = dbConnection;
}

private int sequenceId;

public int getSequenceId() {
    return sequenceId;
}

public void setSequenceId(int sequenceId) {
    this.sequenceId = sequenceId;
}



@Override
/**
 * The method which runs Polling action and record the time at which it is done
 * 
 */
public void run() {
    try {


           incomingMessages.addAll(fullPoll());
            System.out.println("waiting 6 seconds");

            //perform this operation in a loop
            Thread.sleep(6000);

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    Date currentDate = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
//  System.out.println(sdf.format(currentDate) + " " + msg);
}

/**
 * Method which defines polling of the database and also count the number of Queries
 * @return 
 * @throws Exception
 */
public List<KpiMessage> fullPoll() throws Exception {

//  int sequenceID = 0;
    Statement st = dbConnection.createStatement();

    ResultSet rs = st.executeQuery("select * from msg_new_to_bde where ACTION = 804 order by SEQ DESC");
        List<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
        while (rs.next()) {
            KpiMessage filedClass = convertRecordsetToPojo(rs);
            pojoCol.add(filedClass);
        }

        return pojoCol;
        }

/**
 * Converts a provided record-set to a {@link KpiMessage}.
 * 
 * The following attributes are copied from record-set to pojo:
 * 
 * <ul>
 * <li>SEQ</li>
 * <li>TABLENAME</li>
 * <li>ENTRYTIME</li>
 * <li>STATUS</li>
 * </ul>
 * 
 * @param rs
 *            the recordset to convert
 * @return the converted pojo class object
 * @throws SQLException
 *             if an sql error occurrs during processing of recordset
 */
private KpiMessage convertRecordsetToPojo(ResultSet rs) throws SQLException {

    KpiMessage msg = new KpiMessage();
    int sequence = rs.getInt("SEQ");
    msg.setSequence(sequence);
    int action = rs.getInt("ACTION");
    msg.setAction(action);
    String tablename = rs.getString("TABLENAME");
    msg.setTableName(tablename);
    Timestamp entrytime = rs.getTimestamp("ENTRYTIME");
    Date entryTime = new Date(entrytime.getTime());
    msg.setEntryTime(entryTime);
    Timestamp processingtime = rs.getTimestamp("PROCESSINGTIME");
    if (processingtime != null) {
        Date processingTime = new Date(processingtime.getTime());
        msg.setProcessingTime(processingTime);
    }
    String keyInfo1 = rs.getString("KEYINFO1");
    msg.setKeyInfo1(keyInfo1);
    String keyInfo2 = rs.getString("KEYINFO2");
    msg.setKeyInfo2(keyInfo2);
    return msg;
}
}

这里的序列 id 是表中的唯一 id,它随着新的传入消息的到达而不断增加。

P.S :“恳请:请给出给出负分的理由(大拇指向下)。这样我就可以清楚地解释我的问题了”

【问题讨论】:

  • 我 - 我会使用 Quartz 创建一个重复的轮询任务,我会使用 JMS(更具体地说是 HornetQ)来处理消息传递部分。当已经有坚如磐石的轮子可用时,我不喜欢重新发明轮子。
  • 投票?你可以通过触发器引发某种事件吗?
  • @thanks Gimby 我可以知道如何使用石英,这也是一个初学者级别的程序员,还如何使用异步调用这个轮询,就像一个人不断轮询和其他处理消息并更新它...... .
  • @MartinJames 我不知道,我只是卡在这里....
  • 当您没有活动时,轮询是另一种方式。您通过阅读它的手册来学习使用石英,这在一篇文章中无法回答。

标签: java multithreading asynchronous parallel-processing polling


【解决方案1】:

简单地把它放在一个while(true)循环中。

public void run() {
    while(true){
        try {


               incomingMessages.addAll(fullPoll());
                System.out.println("waiting 6 seconds");

                //perform this operation in a loop
                Thread.sleep(6000);

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        Date currentDate = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
    //  System.out.println(sdf.format(currentDate) + " " + msg);
   }
}

希望您已经将 Runnable 作为新线程启动。

对于新的和更新的消息,您需要一个字段,例如数据库中的“last_update”。每次检查新消息时,您都需要更改 SQL 语句以获取新消息,例如:“where last_update &gt; $lastCheckedDate”,其中设置了lastCheckedDate

也许您还想阅读一些有关 Java 并发的内容:http://docs.oracle.com/javase/tutorial/essential/concurrency/

【讨论】:

  • @AdrianThat 可以反复调用轮询,但如何同时检查新消息并更新新消息...?
【解决方案2】:

放入while循环是一种方法,但我认为最好避免采用这种方法(有很多事情要搞砸,比如事务等)。

如果您真的需要做这种重复性的事情,请考虑使用调度程序。 Spring 3.x 确实内置了调度程序,或者您也可以使用 Quartz。

更好的方法是避免这样的轮询。是否可以在更新数据时将消息放入 JMS 队列中,以便一旦 JMS 队列中有此类消息时将调用您的逻辑(通过消息驱动 bean)? (只是一种可能的方法,还有很多类似的方法)

【讨论】:

  • 我认为使用像 Quartz 这样的框架很大程度上取决于应用程序的范围和大小。如果这是您的应用程序需要的唯一“工作”,那么创建线程和轮询是完全有效的。一些搜索还揭示了 Java 的 Timer 和 TimerTask。也许这比 Quartz 更“纤细”一点:stackoverflow.com/questions/1453295/…
  • @Adrian 诚实地使用 Quartz 已经是一个非常苗条的解决方案。鉴于 OP 实际上是在进行数据库访问,我认为我不能将他的应用程序视为那些超级简单的应用程序。而且,使用 Quartz(或其他类型的调度程序)并不困难或笨重。我找不到任何理由避免使用可靠的东西并使我们的应用程序更容易开发。
猜你喜欢
  • 2017-02-07
  • 2011-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2011-04-12
相关资源
最近更新 更多