我有一个多线程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();
}
}
}
但是我在运行程序时仍然收到相同的帐户。我做错了什么?
答案 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();