首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让finally在try-finally中等待线程完成?

如何让finally在try-finally中等待线程完成?
EN

Stack Overflow用户
提问于 2013-05-07 01:31:47
回答 1查看 1.1K关注 0票数 0

我在基于Swing的桌面应用程序中使用JPA。下面是我的代码:

代码语言:javascript
复制
public Object methodA() {

  EntityManager em = emf.createEntityManager();
  em.getTransaction().begin();
  boolean hasError = false;

  try {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
              // JPA operation does not work here 
              // because transaction has been committed!
           }
       });
       ...
       return xXx;
  } catch (Exception ex) {
       hasError = true;
       em.getTransaction().rollback();
  } finally {
       em.close();
       if (!hasError) {
          em.getTransaction().commit();
       }
  }
  return null;    
}

我将这个try - catch - finally用于所有需要事务的方法。除了具有SwingUtilities.invokeLater()的方法之外,它的工作情况与预期一致。

在执行完新线程中的所有代码之前,将会到达finally;因此,如果在SwingUtilities.invokeLater()中有JPA操作,它将失败,因为事务已经被提交。

是否有一个通用的try - catch - finally用例,我可以遵循,以确保事务将只在所有代码执行后才会提交,包括SwingUtilities.invokeLater()中的代码?

EN

回答 1

Stack Overflow用户

发布于 2013-05-07 02:24:19

你必须重新考虑你的方法。首先,SwingUtilities.invokeLater()不是执行JPA操作的最佳选择。该实用程序方法主要目的是更新UI。对于您的代码,为JPA操作实现单独的线程,该线程将接受事务状态的侦听器。一旦交易完成,您将更新UI。

代码语言:javascript
复制
/**
 * Transaction callback.
 */
public interface TransactionListener {
    void onTransactionFinished(boolean hasError);
}

/**
 * Worker Thread which takes data and performs JPA operations.
 */
public class JPATask implements Runnable {
    private final Object dataToPersist;
    private final TransactionListener transactionListener;

    public JPATask(Object dataToPersist,
            TransactionListener transactionListener) {
        this.dataToPersist = dataToPersist;
        this.transactionListener = transactionListener;
    }

    private EntityManager getEntityManager() {/* code is omited */}

    @Override
    public void run() {
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            // perform JPA actions here
            em.getTransaction().commit();
            transactionListener.onTransactionFinished(false);
        } catch (Exception ex) {
            em.getTransaction().rollback();
            transactionListener.onTransactionFinished(true);
        }
    }
}

/**
 * Finally you method. Now it looks like this.
 */
public Object methodA() {
    JPATask jpaTask = new JPATask(<data to persist>, new TransactionListener() {
        @Override
        public void onTransactionFinished(boolean hasError) {
            // Update UI. It's time to use SwingUtilities.invokeLater() 
        }
    }).start();     
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16404001

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档