2013-11-14 6 views
0

Я являюсь пользователем гибернации с гобеленом, и я испытываю проблему, когда мой сеанс остается закрытым, когда я превышу своих Executors.newFixedThreadPool (1);Гобелен Спящий сеанс закрыт после превышения пула потоков исправлений ExecutorService

У меня есть следующий код, который отлично подходит для первого потока, в то время как остальные потоки будут работать с закрытым сеансом. Если я увеличиваю пул потоков до 10, все потоки будут работать без проблем. Как только я превышу fixedThreadPool, я получаю закрытое исключение сеанса. Я не знаю, как открыть его, так как он управляется гобеленом-спящим. Если я использую newCachedThreadPool, все работает отлично. Кто-нибудь знает, что может произойти здесь?

public void setupRender() { 
     ExecutorService executorService = Executors.newFixedThreadPool(1); 

     final ConcurrentHashMap<String, Computer> map = new ConcurrentHashMap<>(); 
     final String key = "myKey"; 

     final Date date = new Date(); 

     List<Future> futures = new ArrayList<>(); 

     for (int i = 0; i < 10; i++) { 
      final int thread = i; 

      Future future = executorService.submit(new Callable() { 

       @Override 
       public String call() { 
        try { 
         Computer computer = new Computer("Test Computer thread"); 
         computer = getComputer(map, key, key, computer); 

         Monitor monitor = new Monitor(); 
         monitor.setComputer(computer); 

         session.save(monitor); 
         session.flush(); 
         System.out.println("thread " + thread); 
         try { 
          sessionManager.commit(); 
         } catch (HibernateException ex) { 
          sessionManager.abort(); 
         } finally { 
          session.close(); 
         } 
        } catch (Exception ex) { 
         System.out.println("ex " + ex); 
        } 
        System.out.println(new Date().getTime() - date.getTime()); 
        return "completed"; 
       }     

      }); 
      futures.add(future); 
     } 

     for(Future future : futures) { 
      try { 
       System.out.println(future.get()); 
      } catch (InterruptedException | ExecutionException ex) { 
       Logger.getLogger(MultiThreadDemo.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 

    public synchronized Computer getComputer(ConcurrentHashMap<String, Computer> map, String key, String thread, Computer computer) { 
     if (map.putIfAbsent(key, computer) == null) { 
      session.save(computer); 
     } else { 
      computer = map.get(key); 
     } 
     return computer; 
    } 

ответ

1

Я говорил вам об этом, прежде чем .... вы должны использовать либо ParallelExecutor ИЛИ позвонить PerThreadManager.cleanup(). Вам нужно понять, что в гобелене-гибернате есть службы PerThread, которые ДОЛЖНЫ быть очищены, если вы используете их вне обычного запроса/ответа (или ParallelExecutor).

Я также не думаю, что вы должны позвонить session.close(). Вы должны mimmic CommitAfterWorker.

Было бы, вероятно, выглядеть так:

@Inject PerThreadManager perThreadManager; 
@Inject HibernateSessionManager sessionManager; // this is a proxy to a per-thread value 
@Inject Session session; // this is a proxy to a per-thread value 

public void someMethod() {  
    ExecutorService executorService = ...; 
    executorService.submit(new Callable() { 
     public String call() { 
      try { 
       Monitor monitor = ... 
       session.save(monitor); 
       session.flush(); // optional 
       sessionManager.commit(); 
      } catch (Exception ex) { 
       sessionManager.abort(); 
      } finally { 
       // this allows Session and HibernateSessionManager to 
       // clean up after themselves 
       perThreadManager.cleanup(); 
      } 
      return ... 
     }     
    }); 
} 

Если вы решили использовать ParallelExecutorInvokable) вместо Executors.newFixedThreadPool(1) вы можете удалить ссылки на PerThreadManager, поскольку она автоматически очищает поток.

+0

Lance, я использую PerThreadManager.cleanup() ;-) Я расширяю WorkQueue, как показано в этом примере, http://wiki.apache.org/tapestry/Tapestry5HowToWorkQueue Все работает отлично, вызывая метод очистки при завершении , Когда я не закрыл соединение, у меня закончилось соединение с базой данных, поэтому я нашел, что это то, что мне нужно было сделать. Я столкнулся с проблемой, когда я ограничил пул потоков, чтобы сказать 1, и поставил 10 задач в пул потоков. Как только я выполнил первую задачу, я получил закрытое исключение сессии. Если я использовал cachedThreadPool, никаких проблем, поэтому я хотел понять, почему. –

+0

В приведенном выше коде показано, что вы отправляете Callable's '' 'Executors.newFixedThreadPool (1)' ''. Нет ссылки на '' 'WorkQueue'' или' '' PerThreadManager.cleanup() '' '. Вы пробовали мой предложенный код? –

+0

Я сегодня вечером, у меня еще не было возможности попробовать. Я просто старался, чтобы мой пример был простым, не думал, что рабочий код очереди был релевантен этой проблеме. Спасибо, копье. –

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