multithreading - Jackrabbit 和并发修改

标签 multithreading concurrency 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 层的情况下进行类似的测试时 - 一切都工作正常。 看起来就像容器包装在自己的事务中,然后全部崩溃。

也许有人遇到过这样的问题。 提前致谢。

最佳答案

来自Jackrabbit Wiki :

The JCR specification explicitly states that a Session is not thread-safe (JCR 1.0 section 7.5 and JCR 2.0 section 4.1.2). Hence, Jackrabbit does not support multiple threads concurrently reading from or writing to the same session. Each session should only ever be accessed from one thread.

... If you need to write to the same node concurrently, then you need to use multiple sessions, and use JCR locking to ensure there is no conflict.

关于multithreading - Jackrabbit 和并发修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6680237/

相关文章:

c++ - 为什么没有发出 QThread::finished 信号?

c# - 带参数启动线程

architecture - 将收到的实时推送数据推送给 10,000 个用户?

python - Django1.6 IntegrityError 尽管有 transaction.atomic()?

java - 扩展 JackRabbit 还是从 Lucene 构建?

c# - web服务中文件下载多线程并发的问题

Java 发生在关系 invokeAndWait 之前

javafx - 为什么 ExecutorService 不返回我的任务结果?

jackrabbit - 关闭 Jackrabbit 的索引功能是否安全?

jackrabbit - 如何使用 MicroKernel 在 JackRabbit Oak 中创建存储库实例