当我运行以下程序时,它不是从主
出来的import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class Ui1 implements Runnable {
private Set<String> set = new HashSet<String>();
public static void main(String[] args) {
Ui1 ui1 = new Ui1();
Thread t = new Thread(ui1);
Thread t1 = new Thread(ui1);
Thread t2 = new Thread(ui1);
Thread t3 = new Thread(ui1);
t.start();
t1.start();
t2.start();
t3.start();
}
final String getUID() {
String uuid = UUID.randomUUID().toString();
StringBuilder builder = new StringBuilder();
builder.append(uuid);
return builder.toString();
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
String s = getUID();
if (!set.add(s)) {
System.out.println(s);
}
}
}
}
当我将迭代次数从1000减少到100时,主电源正常退出
这是Threaddump
2014-04-09 14:42:16
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode):
"DestroyJavaVM" prio=5 tid=0x00007f84b703d800 nid=0x1903 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" prio=5 tid=0x00007f84b400d000 nid=0x5903 runnable [0x0000000117d0e000]
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.put(HashMap.java:498)
at java.util.HashSet.add(HashSet.java:217)
at Ui1.run(Ui1.java:40)
at java.lang.Thread.run(Thread.java:744)
"Service Thread" daemon prio=5 tid=0x00007f84b5843000 nid=0x5303 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=5 tid=0x00007f84b5033000 nid=0x5103 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=5 tid=0x00007f84b400a000 nid=0x4f03 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=5 tid=0x00007f84b502d000 nid=0x4d03 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=5 tid=0x00007f84b5841000 nid=0x3903 in Object.wait() [0x0000000117455000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007aaa85568> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000007aaa85568> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
"Reference Handler" daemon prio=5 tid=0x00007f84b583e800 nid=0x3703 in Object.wait() [0x0000000117352000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007aaa850f0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000007aaa850f0> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=5 tid=0x00007f84b583d800 nid=0x3503 runnable
"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007f84b5013800 nid=0x2503 runnable
"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007f84b5014800 nid=0x2703 runnable
"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007f84b4802000 nid=0x2903 runnable
"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007f84b4802800 nid=0x2b03 runnable
"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007f84b5015000 nid=0x2d03 runnable
"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007f84b5015800 nid=0x2f03 runnable
"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007f84b5016000 nid=0x3103 runnable
"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007f84b5800000 nid=0x3303 runnable
"VM Periodic Task Thread" prio=5 tid=0x00007f84b5843800 nid=0x5503 waiting on condition
JNI global references: 135
Heap
PSYoungGen total 76800K, used 13210K [0x00000007aaa80000, 0x00000007b0000000, 0x0000000800000000)
eden space 66048K, 20% used [0x00000007aaa80000,0x00000007ab766930,0x00000007aeb00000)
from space 10752K, 0% used [0x00000007af580000,0x00000007af580000,0x00000007b0000000)
to space 10752K, 0% used [0x00000007aeb00000,0x00000007aeb00000,0x00000007af580000)
ParOldGen total 174592K, used 0K [0x0000000700000000, 0x000000070aa80000, 0x00000007aaa80000)
object space 174592K, 0% used [0x0000000700000000,0x0000000700000000,0x000000070aa80000)
PSPermGen total 21504K, used 2939K [0x00000006fae00000, 0x00000006fc300000, 0x0000000700000000)
object space 21504K, 13% used [0x00000006fae00000,0x00000006fb0def18,0x00000006fc300000)
答案 0 :(得分:2)
我能够重现这一点(不是100%的时间)。正如 fge 所说,HashSet不是线程安全的,您不应该从不同的线程访问它。这样做的结果是不可预测的。
无论如何,试图解释这个特定的病理,我怀疑内部哈希表结构被破坏了。看起来由于线程之间的竞争条件,桶中的链表变为循环。在这种情况下,put操作会继续无限期地查找列表中的键,这就是导致程序卡住的原因。
请注意,为了重现该问题,我在所有线程上添加了join()命令,否则主线程终止,然后所有线程也终止。
要解决此问题,您可以使用以下方法之一:
答案 1 :(得分:1)
问题是Set set = new HashSet();是从多个线程写的。
有几种方法可以克服这种情况:
正如我所说,在我看来,最好的事情是设计应用程序,尽可能减少线程之间的共享数据。