public String processLine(String line)throws IOException { int min = 1; int max = 100; int randomMillisecconds = min + (int)(Math.random() * ((max - min) + 1)); try { Thread.sleep(randomMillisecconds); } catch (InterruptedException e) { e.printStackTrace(); } // readLineCount is not accurate in multi-thread mode readLineCount++; logger.info(String.format("%d lines were read.", readLineCount)); return line; }
2017-03-01 13:52:04 INFO FileUtil:118 - 2954 lines were read. 2017-03-01 13:52:04 INFO FileUtil:118 - 2955 lines were read. 2017-03-01 13:52:04 INFO FileUtil:118 - 2956 lines were read. 2017-03-01 13:52:04 INFO FileUtil:118 - 2957 lines were read. 2017-03-01 13:52:04 INFO FileUtil:118 - 2958 lines were read. 2017-03-01 13:52:04 DEBUG Starter:50 - Consumer's totalCount: 3000 2017-03-01 13:52:04 INFO Starter:53 - It takes 16 seconds to finish
解释一下,诸如2958 lines were read,是从FileUtil工具类processLine函数中打印出的readLine变量,其代表意义是线程Consumer线程从queue中读取了多少行。Consumer’s totalCount: 3000 是直接打印的Consumer全局变totalCount,其代表意义同样是十个线程总共从queue中读取了多少行,按道理来说,这两个值是应该相同的,然后结果明显不一致。
public String processLine(String line)throws IOException { synchronized (this) { int min = 1; int max = 100; int randomMillisecconds = min + (int) (Math.random() * ((max - min) + 1)); try { Thread.sleep(randomMillisecconds); } catch (InterruptedException e) { e.printStackTrace(); } // readLineCount is not accurate in multi-thread mode readLineCount++; logger.info(String.format("%d lines were read.", readLineCount)); return line; } }
我们再次运行测试脚本:
1 2 3 4 5 6 7 8 9
2017-03-01 14:09:34 INFO FileUtil:119 - 2994 lines were read. 2017-03-01 14:09:34 INFO FileUtil:119 - 2995 lines were read. 2017-03-01 14:09:34 INFO FileUtil:119 - 2996 lines were read. 2017-03-01 14:09:34 INFO FileUtil:119 - 2997 lines were read. 2017-03-01 14:09:35 INFO FileUtil:119 - 2998 lines were read. 2017-03-01 14:09:35 INFO FileUtil:119 - 2999 lines were read. 2017-03-01 14:09:35 INFO FileUtil:119 - 3000 lines were read. 2017-03-01 14:09:35 DEBUG Starter:50 - Consumer's totalCount: 3000 2017-03-01 14:09:35 INFO Starter:53 - It takes 160 seconds to finish
private AtomicInteger readLineCount = new AtomicInteger(0);
processLine函数变为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public String processLine(String line)throws IOException { int min = 1; int max = 100; int randomMillisecconds = min + (int) (Math.random() * ((max - min) + 1)); try { Thread.sleep(randomMillisecconds); } catch (InterruptedException e) { e.printStackTrace(); } // readLineCount is not accurate in multi-thread mode readLineCount.incrementAndGet(); logger.info(String.format("%d lines were read.", readLineCount.get())); return line; }
再次运行测试代码:
1 2 3 4 5 6 7 8 9
2017-03-01 14:18:23 INFO FileUtil:120 - 2994 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 2995 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 2996 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 2997 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 2998 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 2999 lines were read. 2017-03-01 14:18:23 INFO FileUtil:120 - 3000 lines were read. 2017-03-01 14:18:23 DEBUG Starter:50 - Consumer's totalCount: 3000 2017-03-01 14:18:23 INFO Starter:53 - It takes 15 seconds to finish