java - 并发访问 @Lock(LockType.WRITE) 方法

标签 java jakarta-ee concurrency ejb jms

我想实现什么目标:

我有一个 JMS 队列,我想从该队列异步获取元素并发送给打印机。这台打印机非常特殊且愚蠢,因此它无法排队或缓冲任何内容。我必须在此打印机上按顺序执行 5 个步骤,并且排队元素的步骤不得与另一个元素的步骤重叠。对于每一步,打印机将在成功时返回 1,在失败时返回另一个数字。

当前的实现是一个 MDB,它具有从 Singleton ejb 调用 @Lock(LockType.WRITE) 方法的 onMessage 方法。

MDB:

    @MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup",
        propertyValue = "jms/MyQueue"),
@ActivationConfigProperty(propertyName = "destinationType",
        propertyValue = "javax.jms.Queue")})

public class SimpleMessageBean implements MessageListener {

@Resource
private MessageDrivenContext mdc;
static final Logger logger = Logger.getLogger("SimpleMessageBean");

@EJB
private Print print;

public SimpleMessageBean() {
}

@Override
public void  onMessage(Message inMessage) {
    try {
        if (inMessage instanceof TextMessage) {
            logger.log(Level.INFO, "MESSAGE BEAN: Message received: {0}", inMessage.getBody(String.class));

            String params[] = ((TextMessage) inMessage).getText().split("\\s+");
            print.doStuff(params[0], params[1]);
        } else {
            logger.log(Level.WARNING,"Error")
        }
    } catch (Exception e) {
        logger.log(Level.SEVERE, "Rollback Happening: {0}", e.toString());
        mdc.setRollbackOnly();
    }
}

单例:

@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Startup
@Singleton
@AccessTimeout(value = 120000)
public class Print {

static final Logger logger = Logger.getLogger("SimpleMessageBean");

public Print() {
}

@Lock(LockType.WRITE)
public void doStuff(String cpf, String value) throws Exception{
        try{
            int return;
            return = Bematech.AbreCupom(cpf);
            System.out.println("Stage0 = " + return);

            return = Bematech.VendeItem("111112", "Parking", "FF", "hours", "1", 2, value, "%", "00,00");
            System.out.println("Stage1 = " + return);

            return = Bematech.IniciaFechamentoCupom("D", "%", "00,00");
            System.out.println("Stage2 = " + return);

            return = Bematech.EfetuaFormaPagamento("Dinheiro", value);
            System.out.println("Stage3 = " + return);

            return = Bematech.TerminaFechamentoCupom("Thankyou ofr your support");
            System.out.println("Stage4 = " + return);


        }catch ( Exception MensagemErro ){
            throw MensagemErro;
        }
}

我希望这个实现能够从队列接收数据,并在 doStuff() 方法被锁定时一次打印一个元素,又名:

Stage0=1
Stage1=1
Stage2=1
Stage3=1
Stage4=1
Stage0=1
Stage1=1
Stage2=1
Stage3=1
Stage4=1
Stage0=1
...

但有时(似乎是随机的,但当多条消息同时排队时,这种情况更常见)我会同时访问打印方法:

Stage0=1
Stage1=1
Stage0=1
Stage2=1
Stage1=1
Stage3=1
Stage2=1
...

从正在打印的内容中,我可以看到两个元素在打印机访问中重叠。

有用信息:

Java EE 7。 玻璃鱼 4-0。 不使用 JBOSS。

有什么想法为什么会发生这种情况吗?

最佳答案

同步关键字解决了我的问题。没有发现原来的代码有什么问题。

关于java - 并发访问 @Lock(LockType.WRITE) 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22493213/

相关文章:

java - 排序方法运行时崩溃

java - CyclicBarrier 的可见性同步?

java - 获取有关无效 HttpServletRequest session 的信息

java - 编译器的模糊参数,当它对我来说不模糊时

java - 即使未使用步骤定义类,钩子(Hook)执行后的 cucumber 步骤定义类也会执行吗?

java - 如何让 ContainerRequestFilter 过滤多个注释,但在 Java 中一次过滤 1 个注释?

java - 如何在远程 session bean 类中使用 ByteBuffer?

java - Java中的不可重入非阻塞信号量

concurrency - 如何允许更多并发客户端与 Netty 连接?

java - OpenJDK 的 LinkedBlockingQueue 实现 : Node class and GC