Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程在没有通知的情况下死亡_Java_Multithreading_Concurrency_Hashmap - Fatal编程技术网

Java线程在没有通知的情况下死亡

Java线程在没有通知的情况下死亡,java,multithreading,concurrency,hashmap,Java,Multithreading,Concurrency,Hashmap,我正在用HashMap测试并发性(出于学术目的)。我的目标是抛出一些与从多个线程修改映射结构相关的异常 结果是,负责将内容放入我的哈希映射的线程莫名其妙地死亡,而没有抛出任何类型的异常 public class Test { public static void main(String[] args) { Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() { public v

我正在用HashMap测试并发性(出于学术目的)。我的目标是抛出一些与从多个线程修改映射结构相关的异常

结果是,负责将内容放入我的哈希映射的线程莫名其妙地死亡,而没有抛出任何类型的异常

public class Test {
  public static void main(String[] args) {
    Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
      public void uncaughtException(Thread th, Throwable ex) {
        System.out.println("Uncaught exception: " + ex);
      }
    };

    Thread a = new Thread(new MyTask("A"));
    Thread b = new Thread(new MyTask("B"));
    Thread c = new Thread(new MyTask("C"));
    Thread d = new Thread(new MyTask("D"));

    a.setUncaughtExceptionHandler(h);
    b.setUncaughtExceptionHandler(h);
    c.setUncaughtExceptionHandler(h);
    d.setUncaughtExceptionHandler(h);

    a.start();
    b.start();
    c.start();
    d.start();
    while (true) {
      System.out.println(MyTask.map.size());
    }
  }
}

public class MyTask implements Runnable {
  static AtomicInteger counter = new AtomicInteger(0);
  static Map<String, Integer> map = new HashMap<>();
  String name;

  MyTask(String _name) {
    name = _name;
  }

  @Override
  public void run() {
    while (true) {
      counter.incrementAndGet();

      try {
        map.put(name + "_" + counter.get(), counter.get());
      } catch (RuntimeException e) {
        e.printStackTrace();
      }

      System.out.println(name + "_" + counter.get());
    }
   }
 }
公共类测试{
公共静态void main(字符串[]args){
Thread.UncaughtExceptionHandler h=新线程.UncaughtExceptionHandler(){
public void uncaughtException(线程th,可丢弃的ex){
System.out.println(“未捕获异常:+ex”);
}
};
线程a=新线程(newmytask(“a”));
线程b=新线程(newmytask(“b”));
线程c=新线程(newmytask(“c”));
线程d=新线程(newmytask(“d”));
a、 setUncaughtExceptionHandler(h);
b、 setUncaughtExceptionHandler(h);
c、 setUncaughtExceptionHandler(h);
d、 setUncaughtExceptionHandler(h);
a、 start();
b、 start();
c、 start();
d、 start();
while(true){
System.out.println(MyTask.map.size());
}
}
}
公共类MyTask实现Runnable{
静态AtomicInteger计数器=新的AtomicInteger(0);
静态映射映射=新的HashMap();
字符串名;
MyTask(字符串_名称){
名称=_名称;
}
@凌驾
公开募捐{
while(true){
counter.incrementAndGet();
试一试{
map.put(name+“”+counter.get(),counter.get());
}捕获(运行时异常e){
e、 printStackTrace();
}
System.out.println(name+“”+counter.get());
}
}
}
如果运行此操作,您会注意到线程将在某个点停止打印,并且贴图的大小不再改变。如果切换到ConcurrentHashMap,一切正常(它会一直打印)


请让我知道如何捕捉这样的异常/错误

我认为没有出现异常或错误。关于:

请注意,此实现未同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了该映射,则必须在外部对其进行同步

您正在多个线程中修改映射,而不是同步。因此,行为是未定义的

事实上,我无法重现你描述的行为:“地图的大小不再改变”;我看到长期运行时,该值似乎没有改变;但最终它会变成一个新的值,并在那里停留一段时间


这是因为线程中的活动导致的大小更改没有立即提交到主内存。

请看一看。由于您使用的是非同步的
哈希映射

,因此您将自己陷入一个活动锁中,这并不意味着线程写入没有提交到内存中。如果你看我的链接,这是两次或多次写入之间的竞争条件。即使所有字段都是易变的,这仍然可能失败。有趣!谢谢。(:男孩,那篇博文确实很长!通过从
run()
中删除
println()
s,我能够重现这个问题(我想这增加了我的重叠机会,因为打印需要一些时间)。这是正确的答案->并发
HashMap
大小调整可以在存储桶列表中创建一个循环,使其无法迭代到某些元素。@JanezKuhar println是同步的,它间接引入了数据可见性的度量。感谢您的答案和有趣的链接!我想我只能选择一个答案。:CIt doesn不会死,它会进入无限循环,因为HashMap不是线程安全的。您不会期望它显示错误,而是消耗100%的CPU。