0

我需要从表中读取数据并对每一行做一些工作并将该行标记为已更新。我不想再次阅读更新的行。这是我打算用 ExecutorService 做的事情。这个对吗 ?

谢谢。

public class ScheduledDBPoll
{
    public static void main(String args[])
    {
        ExecutorService service = Executors.newFixedThreadPool(10);
        /* Connect to database. */
        while (true)
        {
        /* Issue a select statment for un-updated rows. */
            /* Get the primary key. */

            service.submit(new Task(primaryKey));      /* Pass the primary key*/
            try
            {
                Thread.sleep(3000);     /* Sleep for 3 seconds. */
            }
            catch (InterruptedException ex)
            {
                Logger.getLogger(ScheduledDBPoll.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        /* Close the connection here. */
    }
}

final class Task implements Runnable
{
    private int taskId;

    public Task(int primayKey)
    {
        this.taskId = primayKey;
    }

    @Override
    public void run()
    {
        try
        {
            /* Connect to database. */
            /* Select the passed primary key row. */
            /* Do some work,  mark the row as updated. */
            /* Close the connection here. */            
        }
        catch (InterruptedException ex)
        {
            Logger.getLogger(Task.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

我正在使用 Firebird 数据库,Firebird 仅在连接级别是线程安全的。因此,我试图避免在针对同一连接运行的不同线程中进行两个查询。我还忘了提到上面的代码将作为 Windows 服务运行,所以它总是在寻找新插入的记录。

4

2 回答 2

1

我会使用 ScheduledExecutorService 并且没有每三秒发送一次作业的线程。我也会保持连接打开,因为创建数据库连接非常慢。

所以我会更像

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Task(), 1, 1, TimeUnit.SECONDS);


final class Task implements Runnable {
    private Connection connection;
    private int taskId;

    @Override
    public void run() {
        try {
            if (!connectionIsOkay()) {
                connectToDatabase();
                taskId = selectUnUpdatedRow();
            }
            selectRowsToUpdate();
            processRowsToUpdate();
            markAsUpdated();

        } catch (Exception ex) {
            Logger.getLogger(Task.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    // TODO find a more elegant way to close the connection when finished.
    public void finalise() {
        closeConnection();
    }
}
于 2013-10-13T14:37:58.947 回答
0

首先,一个可能很重要的术语问题:这段代码没有实现“一个”工作线程;它尝试同时从多达 10 个线程进行并发数据库访问。

所以如果你真的想要一个工作线程,你的固定线程池需要大小为 1,而不是 10。但是你可能不需要单独的任务,你可能有一个任务来处理所有事情,整个事情变得更简单。

我不知道您为什么要等待 3 秒(实际上是一秒,尽管您的评论说了什么),这似乎毫无意义。

除此之外,它似乎是正确的。

于 2013-10-13T14:31:12.400 回答