I work on a data processing application in which concurrency is achieved by putting several units of work on a message queue that multiple instances of a message driven bean
There are two additional bonuses that I don't think has been mentioned: Transactions and durability.
While it isn't required and quite often isn't the default configuration, JMS providers can be configured to persist the messages and also to participate in a XA transaction with little or no code changes.