异步多线程消息处理

时间:2012-12-19 10:45:35

标签: java-ee java-ee-6 ejb-3.1

Java 7,Glassfish 3.1.2

输入是以下消息:

public class Message {

    private final String contextId;
    private final String name;
    ...
}

此消息应由工作人员处理。对于具有新contextId的消息 应该启动一个新线程。对于已存在的contextId,使用已存在的线程。现有的线程应该使用相同的contextId顺序处理消息。

Hier my last,not working,Worker version。

@Stateless
@LocalBean
public class Worker {

private static final Map<String, Future<Result>> MAP = new ConcurrentHashMap<>();
@EJB
private Worker worker;

@Asynchronous
public void work(Message message) {
    System.out.println(Thread.currentThread().getName() + ": A  message: " + message.toString()+ " should be processed");
    Future<Result> sameContext = MAP.get(message.getContextId());
    if (sameContext != null) {
        waitForSameContextId(message, sameContext);
    }
    MAP.put(message.getContextId(), worker.doWork(message));
}

@Asynchronous
public Future<Result> doWork(Message message) {
    System.out.println(Thread.currentThread().getName() + ": Processing the message:  " + message.toString());

    AsyncResult<Result> asyncResult = new AsyncResult<>(new Result());
    try {
        Thread.sleep(15000);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }

    MAP.remove(message.getContextId());  //We are done removing 
    System.out.println(Thread.currentThread().getName() + ": The message: " + message.toString()+ " was processed");
    return asyncResult;
}

private void waitForSameContextId(Message message, Future<Result> result) {
    try {
        System.out.println(Thread.currentThread().getName() + ": message with id: " + message.toString()
                + " is already in work, blocking Thread until it is finished");
        Result get = result.get(); //blocks thread
    } catch (InterruptedException | ExecutionException ex) {
        ex.printStackTrace();
        // Do some failure management
    }
}

测试类:

public class MessageReceiver {

private static String ID = "#########";

@EJB
private Worker worker;

public void receive(Message message) {

    worker.work(message);
}

@PostConstruct
void init() {

    receive(new Message(ID, "message 1"));
    receive(new Message(ID, "message 2"));
    receive(new Message(ID, "message 3"));
 ...
 }

1 个答案:

答案 0 :(得分:0)

我认为您可以使用CDI @Observes模式调用@Asynchronous服务。 如需深入解释,请查看此链接http://www.devchronicles.com/2011/12/javaee-revisits-design-patterns_28.html