Java synchronized块无法正常工作

时间:2015-07-04 02:52:15

标签: java multithreading

我有一个多线程java应用程序,它从Postgresql数据库中检索用户名以进行处理。

我只希望每个线程一次处理一个帐户,所以我的表中有一个列,其中包含上次访问的时间戳,只会获取访问时间超过30秒的帐户。 SQL查询在下面工作,我只是将其发布为明确的。

select * from account where (EXTRACT(EPOCH FROM (now() - last_accessed)) > 30 OR last_accessed is null) AND enabled = true order by random() limit 1

我有一个同步块,因此只有一个线程可以访问帐户检索过程,因为更新时间戳会占用数据库的时间。

public class TC extends Common implements Runnable
{
    RegularExpr reg = new RegularExpr();
    Database        db  = new Database();

    public void run()
    {
        while (true)
        {
            try
            {
                ArrayList<Object> accountInfo = null;

                synchronized (this)
                {
                    accountInfo = db.getAccount();
                    db.updateAccountAccessTime((String) accountInfo.get(0));
                    Thread.sleep(3000);
                }
                System.out.println((String) accountInfo.get(0));
                Thread.sleep(9999999);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

我的主要课程

public class Main
{
    public static void main(String[] args)
    {

        for (int i = 0; i < 3; i++)
        {
            System.out.println("Inside loop to create threads!");
            Thread newThread = new Thread(new TC());
            newThread.start();
        }
    }
}

但是我在运行程序时仍然收到相同的帐户。我做错了什么?

2 个答案:

答案 0 :(得分:3)

每个线程都使用不同的TC实例执行。

new Thread(new TC())

所以当你这样做时:

synchronized (this)

每个线程在不同的对象(不同的TC)上进行同步,因此它们根本不会相互竞争。从本质上讲,同步块变得毫无意义。

我不确定这是一个多么好的想法,但你想要做的就是这样完成:

synchronized (TC.class)

或者,或许更清洁一点,通过在类中声明一个静态成员并同步它:

private static final Object _lock = new Object();

....

synchronized(_lock)

答案 1 :(得分:0)

当有共享资源和多个线程访问它时,整个同步点就是。

在你的情况下,可以将相同的TC实例传递给新的Thread.then 3个线程开始处理它。

现在需要保护db操作,因为您需要获取帐户信息并更新timestamp.so特定于锁定对象或同步。

private Object lock = new Object();