From b84be5b4b96318348ce0209aa38335372aeae94b Mon Sep 17 00:00:00 2001 From: LiuXianfa Date: Mon, 10 Jun 2019 18:35:22 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=9C=A8=E5=A4=9A=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E5=9C=BA=E6=99=AF=E4=B8=8B=EF=BC=8C=E6=89=93=E5=8D=B0?= =?UTF-8?q?Vector=E4=B8=AD=E7=9A=84=E6=AF=8F=E4=B8=AA=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...rintEachElementFromVectorInMoreThread.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 java/PrintEachElementFromVectorInMoreThread.java diff --git a/java/PrintEachElementFromVectorInMoreThread.java b/java/PrintEachElementFromVectorInMoreThread.java new file mode 100644 index 0000000..a615419 --- /dev/null +++ b/java/PrintEachElementFromVectorInMoreThread.java @@ -0,0 +1,108 @@ +import java.util.Vector; +import java.util.concurrent.CyclicBarrier; + +/** + *
+ *
+ * 在多线程的场景下,打印java.util.Vector中的每个元素。
+ *
+ *      我们都知道,在多线程场景下不能使用ArrayList,应该用Vector,因为别人都告诉我们Vector是线程安全的。
+ *      但其实,这里是有坑的!!!>_<啊啊啊啊啊啊啊啊啊~
+ *
+ *      代码发到生产环境后却发现总是报错:java.util.ConcurrentModificationException
+ *
+ *      例如在下面的代码中,遍历容器 Vector只是简单的把每个元素打印出来,这就存在并发问题。
+ *      那么个问题如何修改呢?大家可以试一下。
+ * 
+ * + * @author AnXiaole + * @date 2019/6/10 17:17 + */ +public class PrintEachElementFromVectorInMoreThread { + + public static void main(String[] args) throws InterruptedException { + + error(); // 错误情况演示 + + // correct(); // 如果想要尝试修改,可在correct()方法中修改。 + } + + /** + * 执行一下,应该会报如下异常: + *
+     *     Exception in thread "Thread-0" java.util.ConcurrentModificationException
+             at java.util.Vector$Itr.checkForComodification(Vector.java:1184)
+             at java.util.Vector$Itr.next(Vector.java:1137)
+             at PrintEachElementFromVectorInMoreThread.lambda$error$0(PrintEachElementFromVectorInMoreThread.java:36)
+             at java.lang.Thread.run(Thread.java:745)
+     * 
+ */ + private static void error() { + // 实际上我的业务代码是没有CyclicBarrier的,CyclicBarrier只是为了演示多个线程'同时'执行的情况。 + // new Thread()的过程比较慢,如果这里不加CyclicBarrier,可能第二个线程还没创建好,第一个线程就执行完了。从而打不到多线程同时执行的目的。 + // 也是因为测试环境并发量比较小导致在测试环境根本就没有发现这个bug。>_< + CyclicBarrier cyclicBarrier = new CyclicBarrier(2); + + + Vector numbers = new Vector<>(); + + new Thread(() -> { + try { + cyclicBarrier.await(); + } catch (Exception e) { + } + + for (int i = 0; i < 1000; i++) { + numbers.add(i); + } + }).start(); + + + new Thread(() -> { + try { + cyclicBarrier.await(); + } catch (Exception e) { + } + + for (int i = 0; i < 10; i++) { + for (Integer number : numbers) { + System.out.println(number); + } + } + }).start(); + } + + /** + * 大家可以尝试再这里修改并提交修改后的代码。 + */ + private static void correct() { + CyclicBarrier cyclicBarrier = new CyclicBarrier(2); + Vector numbers = new Vector<>(); + + + new Thread(() -> { + try { + cyclicBarrier.await(); + } catch (Exception e) { + } + + for (int i = 0; i < 10; i++) { + for (Integer number : numbers) { + System.out.println(number); + } + } + }).start(); + + new Thread(() -> { + try { + cyclicBarrier.await(); + } catch (Exception e) { + } + + for (int i = 0; i < 1000; i++) { + numbers.add(i); + } + }).start(); + } + +} -- Gitee From 15d1fcb5fb7b6d92db0828894590782845fc40f5 Mon Sep 17 00:00:00 2001 From: LiuXianfa Date: Mon, 10 Jun 2019 18:36:50 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=9C=A8=E5=A4=9A=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E5=9C=BA=E6=99=AF=E4=B8=8B=EF=BC=8C=E6=89=93=E5=8D=B0?= =?UTF-8?q?Vector=E4=B8=AD=E7=9A=84=E6=AF=8F=E4=B8=AA=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java/PrintEachElementFromVectorInMoreThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/PrintEachElementFromVectorInMoreThread.java b/java/PrintEachElementFromVectorInMoreThread.java index a615419..3025fc2 100644 --- a/java/PrintEachElementFromVectorInMoreThread.java +++ b/java/PrintEachElementFromVectorInMoreThread.java @@ -9,7 +9,7 @@ import java.util.concurrent.CyclicBarrier; * 我们都知道,在多线程场景下不能使用ArrayList,应该用Vector,因为别人都告诉我们Vector是线程安全的。 * 但其实,这里是有坑的!!!>_<啊啊啊啊啊啊啊啊啊~ * - * 代码发到生产环境后却发现总是报错:java.util.ConcurrentModificationException + * 代码发到生产环境后却发现经常报错:java.util.ConcurrentModificationException * * 例如在下面的代码中,遍历容器 Vector只是简单的把每个元素打印出来,这就存在并发问题。 * 那么个问题如何修改呢?大家可以试一下。 -- Gitee