I have a piece of code where different threads manipulating the HashMap. I have to synchronize this piece of code. Later, I want to test this using开发者_开发知识库 JUnit. So is it possible to test multithreading using JUnit? If yes could you please give me an example.
Absolutely, but it's not easy.
There's an excellent chapter on this topic in Freeman & Pryce's "Growing Object Oriented Software" book, which I can highly recommend.
I've actually done this, but only for simple multi threadded scenarios. Basically, what you want is to synchronise the access of multiple threads towards your hashmap, or in other words, to have a predictable order in which a bunch of threads to things on the hash map. You could build test cases where each Thread logs in the nanotime and some unique id each time it does something, and then have an assert on these log entries (which can be kept in memroy, they don't have to to be outputted to an actual file) that checks if they're in the correct order.
Here's an example of how I unit test multiple (well actually it's just 2) threads accessing the database, to make sure that they do it in the order I expect them to do it:
@Test
public void testPessimisticLock3_write_blocking() throws Throwable {
init();
final ArrayList<String> eventsOrder = new ArrayList<String>();
Department d = new Department();
d.setName("d");
em.getTransaction().begin();
em.persist(d);
em.getTransaction().commit();
id=d.getId();
em.getTransaction().begin();
//aquire lock:
@SuppressWarnings("unused")
Department dRet1 = em.find(Department.class, d.getId(),LockModeType.PESSIMISTIC_WRITE);
eventsOrder.add("First transaction got the lock");
// dRet1.setName("dRet1");
eventsOrder.add("First transaction will sleep for a while...");
Thread.sleep(1500);
new Thread(new Runnable() {
@Override
public void run() {
em2.getTransaction().begin();
//this will wait for the first transaction to release the lock, so that this 2nd transaction can acquire the lock
eventsOrder.add("Second transaction will now try to get the lock...");
em2.find(Department.class, id,LockModeType.PESSIMISTIC_WRITE);
eventsOrder.add("Second transaction got the lock.");
em2.getTransaction().commit();
assertEquals("First transaction got the lock",eventsOrder.get(0));
assertEquals("First transaction will sleep for a while...",eventsOrder.get(1));
assertEquals("Second transaction will now try to get the lock...",eventsOrder.get(2));
assertEquals("First transaction woke up and will commit...",eventsOrder.get(3));
assertEquals("First transaction has commited.",eventsOrder.get(4));
assertEquals("Second transaction got the lock.",eventsOrder.get(5));
}
}).start();
Thread.sleep(1500);
eventsOrder.add("First transaction woke up and will commit...");
em.getTransaction().commit();
eventsOrder.add("First transaction has commited.");
}
精彩评论