2015-07-04 9 views
2

У меня есть многопоточное java-приложение, которое извлекает имена пользователей из базы данных Postgresql для обработки.Java синхронизированный блок не работает

Я хочу, чтобы одна учетная запись обрабатывалась одновременно по каждому потоку, поэтому у меня есть столбец в моей таблице, у которого есть отметка времени последнего доступа, и будут получены только учетные записи, которые были доступны более 30 секунд. SQL Query работает ниже, я только публикую его, чтобы быть ясным.

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(); 
     } 
    } 
} 

Но я все еще получаю ту же учетную запись при запуске программы. Что я делаю неправильно?

ответ

3

Каждый поток исполняется с другим экземпляром TC.

new Thread(new TC()) 

Так что, когда вы делаете:

synchronized (this) 

Каждый поток синхронизации на другом объекте (разные TC), поэтому они не конкурируют друг с другом на всех. По сути, синхронизированный блок становится бессмысленным.

Я не уверен, насколько хорошо идея это, но то, что вы пытаетесь сделать, будет осуществляться следующим образом:

synchronized (TC.class) 

или, возможно, немного чище, объявив статический член в класс и синхронизация на этом:

private static final Object _lock = new Object(); 

.... 

synchronized(_lock) 
+0

Как я могу достичь того, что мне нужно? – Arya

+0

Вам понадобится использовать статический конечный объект на TC-классе и использовать его для синхронизации вместо этого. – Codebender

0

Весь смысл синхронизации, когда к нему подключен общий ресурс и несколько потоков.

В вашем случае тот же экземпляр TC может быть передан в новую Thread.then. На нем начинают работать 3 потока.

Теперь операция db должна быть защищена, так как вам нужно получить информацию об учетной записи, а также синхронизировать синхронизацию timestamp.so на объекте блокировки.

private Object lock = new Object();

Смежные вопросы