2011-07-13 84 views
3

在我們對使用jackrabbit的應用程序進行了一些性能測試後,我們遇到了併發修改jackrabbit庫的巨大問題。當我們添加節點或在多線程仿真中編輯它們時,會出現問題。然後,我寫了一個非常簡單的測試,告訴我們問題不在我們的環境中。Jackrabbit和併發修改

有它:

簡單的無狀態的Bean

 

    @Stateless 
     @Local(TestFacadeLocal.class) 
     @Remote(TestFacadeRemote.class) 
     public class TestFacadeBean implements TestFacadeRemote, TestFacadeLocal { 
      public void doAction(int name) throws Exception { 
       new TestSynch().doAction(name); 
      } 
     } 

簡單類

 

    public class TestSynch { 
     public void doAction(int name) throws Exception { 
      Session session = ((Repository) new InitialContext(). 
        lookup("java:jcr/local")).login(
        new SimpleCredentials("username", "pwd".toCharArray())); 
      List added = new ArrayList(); 
      Node folder = session.getRootNode().getNode("test"); 
      for (int i = 0; i <= 100; i++) { 
       Node child = folder.addNode("" + System.currentTimeMillis(), 
           "nt:folder"); 
       child.addMixin("mix:versionable"); 

       added.add(child); 
      } 
      // saving butch changes 
      session.save(); 

      //checking in all created nodes 
      for (Node node : added) { 
       session.getWorkspace().getVersionManager().checkin(node.getPath()); 
      } 
     } 
    } 

與測試類

 

    public class Test { 
     private int c = 0; 
     private int countAll = 50; 
     private ExecutorService executor = Executors.newFixedThreadPool(5); 

     public ExecutorService getExecutor() { 
      return executor; 
     } 

     public static void main(String[] args) { 
      Test test = new Test(); 
      try { 
       test.start(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     private void start() throws Exception { 
      long time = System.currentTimeMillis(); 
      TestFacadeRemote testBean = (TestFacadeRemote) getContext(). 
             lookup("test/TestFacadeBean/remote"); 
      for (int i = 0; i < countAll; i++) { 
       getExecutor().execute(new TestInstallerThread(i, testBean)); 
      } 

      getExecutor().shutdown(); 
      while (!getExecutor().isTerminated()) { 
       try { 
        Thread.sleep(500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(c + " shutdown " + 
           (System.currentTimeMillis() - time)); 

     } 

     class TestInstallerThread implements Runnable { 
      private int number = 0; 
      TestFacadeRemote testBean; 

      public TestInstallerThread(int number, TestFacadeRemote testBean) { 
       this.number = number; 
       this.testBean = testBean; 
      } 

      @Override 
      public void run() { 
       try { 
        System.out.println("Installing data " + number); 
        testBean.doAction(number); 
        System.out.println("STOP" + number); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        c++; 
       } 
      } 

     } 

     public Context getContext() throws NamingException { 
      Properties properties = new Properties(); 
      //init props 
      .............. 
      return new InitialContext(properties); 
     } 
    } 

如果我在池1個線程初始化執行人我完成沒有任何錯誤。如果我用5線程初始化執行我有時錯誤:

客戶端

 
    java.lang.RuntimeException: javax.transaction.RollbackException: [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] Can't commit because the transaction is in aborted state 
     at org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:198) 

在服務器開頭警告

 
    ItemStateReferenceCache [ItemStateReferenceCache.java:176] overwriting cached entry 187554a7-4c41-404b-b6ee-3ce2a9796a70 

然後

 
    javax.jcr.RepositoryException: org.apache.jackrabbit.core.state.ItemStateException: there's already a property state instance with id 52fb4b2c-3ef4-4fc5-9b79-f20a6b2e9ea3/{http://www.jcp.org/jcr/1.0}created 
     at org.apache.jackrabbit.core.PropertyImpl.restoreTransient(PropertyImpl.java:195) ~[jackrabbit-core-2.2.7.jar:2.2.7] 
     at org.apache.jackrabbit.core.ItemSaveOperation.restoreTransientItems(ItemSaveOperation.java:879) [jackrabbit-core-2.2.7.jar:2.2.7] 

我們已經嘗試將此方法和其他工作流程同步爲一個線程處理多線程調用。沒什麼幫助。

還有一件事 - 當我們做了沒有ejb層的類似測試時 - 一切正常。 它看起來像容器包裝在自己的交易,然後全部墜毀。

也許有人遇到這樣的問題。 在此先感謝。

回答

5

Jackrabbit Wiki

的JCR說明書中明確指出,一個會話不是線程安全(JCR 1.0 7.5節和2.0 JCR部分4.1.2)。因此,Jackrabbit不支持同時讀取或寫入同一會話的多個線程。每個會話只能從一個線程訪問。

... 如果您需要同時寫入同一個節點,那麼您需要使用多個會話,並使用JCR鎖定來確保沒有衝突。

+0

而且我總是新的會議。 '新TestSynch()doAction(名稱)' '屆會議=((庫)新的InitialContext() 查找(的 「java:JCR /本地」))。登錄( 新SimpleCredentials( 「用戶名」, 「PWD」 .toCharArray()));' – travmik