试图实现一个工作线程

时间:2013-10-13 14:22:37

标签: java multithreading executorservice

我需要从表中读取数据并对每一行执行一些操作并将该行标记为已更新。我不想再次阅读更新的行。这是我打算用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服务运行,所以它总是会寻找新插入的记录。

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:0)

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

因此,如果您真的 实际上只需要一个工作线程,那么您的固定线程池需要大小为1,而不是10.然后您可能不需要单独的任务,您可能需要一个所有事情的任务,整个过程变得更加简单。

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

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