在阅读JCIP的时候想手工测试一下,结果发现总是没有出现书中描述的并发问题
后来我琢磨,以前记得书上说过,在debugging的环境下,JVM是低并发的,一定要在server的环境下测试,让JVM在高并发的情况下使用,才容易测试出并发BUG,最简便的方法就是给JVM添加上-server的运行参数
代码如下,JCIP Listing3.15
1 class Holder { 2 private int n; 3 private static Random random = new Random(); 4 public Holder(int n) { 5 this.n = n; 6 } 7 public void changeValue() { 8 n = random.nextInt(); 9 } 10 public void assertSanity() { 11 if (n != n) { 12 throw new AssertionError("n != n"); 13 } 14 } 15 } 16 17 class Checker implements Runnable { 18 private boolean stop = false; 19 private Holder holder; 20 public Checker(Holder holder) { 21 this.holder = holder; 22 } 23 public synchronized void stop() { 24 stop = true; 25 } 26 @Override 27 public void run() { 28 while (!stop) { 29 try { 30 // System.out.println("checking"); 31 holder.assertSanity(); //! Possible to throw exception in concurrent circumstances 32 } catch (Throwable e) { 33 System.out.println(e); 34 stop(); 35 } 36 } 37 } 38 } 39 40 class Modifier implements Runnable { 41 private boolean stop = false; 42 private Holder holder; 43 public Modifier(Holder holder) { 44 this.holder = holder; 45 } 46 public synchronized void stop() { 47 stop = true; 48 } 49 @Override 50 public void run() { 51 while (!stop) { 52 // System.out.println("modifying"); 53 holder.changeValue(); 54 } 55 } 56 } 57 58 public class Listing3_15 { 59 public static void main(String[] args) { 60 ExecutorService exec = null; 61 Holder holder = null; 62 Modifier m1 = null, m2 = null; 63 Checker checker = null; 64 Scanner scanner = null; 65 try { 66 exec = Executors.newCachedThreadPool(); 67 holder = new Holder(10); 68 m1 = new Modifier(holder); 69 m2 = new Modifier(holder); 70 checker = new Checker(holder); 71 exec.execute(checker); 72 exec.execute(m1); 73 exec.execute(m2); 74 scanner = new Scanner(System.in); 75 scanner.next(); // pause 76 } finally { 77 m1.stop(); 78 m2.stop(); 79 checker.stop(); 80 exec.shutdown(); 81 scanner.close(); 82 } 83 } 84 }
果然,在debug的环境下,JVM跑不出这个并发BUG,添加-server参数之后,JVM就跑出这个并发BUG了,在eclipse中设置-server参数的方法如下:Run>Run Configurations>Arguments>VM Arguments,写上-server即可