1 package com.fasterxml.jackson.databind.misc; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.Date; 6 import java.util.List; 7 import java.util.concurrent.*; 8 import java.util.concurrent.atomic.AtomicInteger; 9 10 import com.fasterxml.jackson.databind.*; 11 12 public class ThreadSafety1759Test extends BaseMapTest 13 { 14 /* 15 /********************************************************** 16 /* Test methods 17 /********************************************************** 18 */ 19 testCalendarForDeser()20 public void testCalendarForDeser() throws Exception 21 { 22 final ObjectMapper mapper = newJsonMapper(); 23 24 final int numThreads = 4; 25 final int COUNT = 3000; 26 final AtomicInteger counter = new AtomicInteger(); 27 28 // IMPORTANT! Use different timestamp for every thread 29 List<Callable<Throwable>> calls = new ArrayList<Callable<Throwable>>(); 30 for (int thread = 1; thread <= numThreads; ++thread) { 31 final String json = quote(String.format("2017-01-%02dT16:30:49Z", thread)); 32 final long timestamp = mapper.readValue(json, Date.class).getTime(); 33 34 calls.add(createCallable(thread, mapper, json, timestamp, COUNT, counter)); 35 } 36 37 ExecutorService executor = Executors.newFixedThreadPool(numThreads); 38 List<Future<Throwable>> results = new ArrayList<>(); 39 for (Callable<Throwable> c : calls) { 40 results.add(executor.submit(c)); 41 } 42 executor.shutdown(); 43 for (Future<Throwable> f : results) { 44 Throwable t = f.get(5, TimeUnit.SECONDS); 45 if (t != null) { 46 fail("Exception during processing: "+t.getMessage()); 47 } 48 } 49 assertEquals(numThreads * COUNT, counter.get()); 50 } 51 createCallable(final int threadId, final ObjectMapper mapper, final String json, final long timestamp, final int count, final AtomicInteger counter)52 private Callable<Throwable> createCallable(final int threadId, 53 final ObjectMapper mapper, 54 final String json, final long timestamp, 55 final int count, final AtomicInteger counter) 56 { 57 return new Callable<Throwable>() { 58 @Override 59 public Throwable call() throws IOException { 60 for (int i = 0; i < count; ++i) { 61 Date dt = mapper.readValue(json, Date.class); 62 if (dt.getTime() != timestamp) { 63 return new IllegalArgumentException("Wrong timestamp (thread id "+threadId+", input: "+json+": should get "+timestamp+", got "+dt.getTime()); 64 } 65 counter.addAndGet(1); 66 } 67 return null; 68 } 69 }; 70 } 71 } 72