Spring同步问题

时间:2013-09-09 13:42:34

标签: java spring synchronization

我知道有关重复使用原型bean的问题被多次询问,但我的问题意味着更多。

有什么问题:

我在for-lookup中的handler(prototype bean)中启动异步任务。但是我无法在上一次达到某个里程碑之前启动下一个异步任务。因此,只有在上一个任务调用特殊方法后才能进行循环。

问题:

  1. 如何在另一个bean调用某个方法之前等待for循环?
  2. 我可以从另一个bean调用当前原型bean的proceedLookUp()方法吗?

  3. @Service(value = "Request.Start")
    @Scope("prototype")
    public static class Start {
    
      public Start() {}
    
      private Object lock;
    
      @Transactional
      public void handler(Request request, Response response) {
    
        for (int i = 0; i < request.getAmount(); i++) {
          Utils.asyncProcessStart(); //Can't start the next async process before the previous rich some defined milestone
          lock.wait();
        }
      }
    
      public void proceedLookUp() {
        lock.notify();
      }
    }
    
    @Service
    public void AsynchronousTask {
    
      public void asyncAction() [
        //Needed logic, before start the next async task
        getStartHandler().proceedLookUp();
      }
    
      public void getStartHandler() {
        //HOW TO REWRITE NEEDED PROTOTYPE BEAN
      } 
    }
    

    此外:

    有什么问题 :我使用Activiti框架,这意味着一些限制。我应该将一些变量存储到进程(线程)上下文中。我可以将变量写入全局上下文,但是在进程(线程)启动之前不能写入本地进程(线程)上下文。

      

    你期望发生什么,比如request.getAmount()是否返回2?

    我应该在两个不同的线程中启动两个异步进程。每个流程都有相同的变量集。我必须将适当的变量写入每个进程(线程)的本地上下文。但是,我不能在流程(线程)启动之前执行(由于Activiti框架的特定)。

    例如,每个进程(线程)都应将“id”属性写入其自己的本地上下文。我在处理程序方法

    中有 List ids

    所以,我应该采取下一步行动:

    1. 将ids.get(0)写为“id”-property到GLOBAL context
    2. 开始第一个过程
    3. 挂在for-loop
    4. [在第一个过程中]从全局到本地上下文写入“id”属性(可以在第一个过程中)
    5. 通知相应的Start bean,它可以继续for-loop
    6. 将ids.get(1)写为“id”-property到GLOBAL context
    7. 开始第二个过程
    8. 挂在for-loop
    9. [在第二个过程中]从全局到本地上下文写入“id”属性(可以在第二个过程中)
    10. 通知相应的Start bean,它可以继续for-loop
    11.   

      为什么你不能同步调用它?

      正如您已经了解的那样,在第二个进程(线程)的for循环覆盖它之前,不能保证第一个进程(线程)将“id”属性写入它的本地上下文。 / p>

1 个答案:

答案 0 :(得分:4)

这是我的建议:创建一个单例对象,您可以在线程之间共享以传递信息(状态)。单例使用semaphore来协调线程。您可以使用此方法将新线程的标识传递回Service类。这是一个简单的例子,展示了我的建议。

测试类:

公共类TestSemaphore {

    @Test
    public void test() throws Exception {

        ThreadCoordinator tc = ThreadCoordinator.getInstance();

        for( int i = 0; i < 100; i++ ) {
            MyThread r = new MyThread();
            r.run();

            // This will block until the Thread has called release (after setting its identity on the ThreadCoordinator)    
            tc.acquire();
            String newThreadIdentity = tc.getIdentity();
            System.out.println( "Received the new thread's identity:         " + newThreadIdentity );

            // This will allow the next Thread to acquire the semaphore
            tc.release();
        }
    }


    class MyThread extends Thread {

        public void run() {
            String identity = Integer.toString( (int)(Math.random() * 10000) );
            System.out.println( "Running a new thread with identity:         " + identity );

            // Get a reference to the singleton
            ThreadCoordinator tc = ThreadCoordinator.getInstance();
            try {
                tc.acquire();
                tc.setIdentity( identity );
                System.out.println( "Notified the ThreadCoordinator from thread: " + identity );
                tc.release();
            } catch( InterruptedException e ) {
                System.out.println( "Caught an interrupted exception: " + e );
            }

        }

    }
}

ThreadCoordinator(信号量)类:

import java.util.concurrent.Semaphore;

public class ThreadCoordinator {

        private static ThreadCoordinator tc = new ThreadCoordinator();
        private static Semaphore semaphore = new Semaphore( 1, true );      
        private static String identity;

        // singleton get instance
        public static ThreadCoordinator getInstance() {
            return ThreadCoordinator.tc;
        }

        public void setIdentity( String identity ) throws InterruptedException {
            ThreadCoordinator.identity = identity;
        }


        public String getIdentity() throws InterruptedException {
            String identity = ThreadCoordinator.identity;
            ThreadCoordinator.identity = null;
            return identity;
        }

        public void acquire() throws InterruptedException {
            ThreadCoordinator.semaphore.acquire();
        }

        public void release() {
            ThreadCoordinator.semaphore.release();
        }

 }