【问题标题】:How can I ensure that every thread is working on the same object?如何确保每个线程都在同一个对象上工作?
【发布时间】:2021-02-02 17:15:20
【问题描述】:

如何确保每个线程都在同一个对象上工作?我们在 8 个并行线程上执行回归。我想将特定于线程的日志存储在地图中,然后在运行后对其中的数据进行处理。

public class Foo {
   // map with thread name as a key and queue to keep its logs
   public static final Map<String, LinkedList<String>> foofoo = new ConcurrentHashMap<>();
   
   
   public static void addToQueue(String threadName, String log) {
      //some logic here to add log to proper queue
   }
}

我想确保每当任何正在运行的线程调用时:

Foo.addToQueue("foo", "fooo");

它正在访问同一个地图。 谢谢你的回复。我对多线程有点困惑,如果问题有点愚蠢,对不起。 祝你今天过得愉快! :)

编辑:在上面的示例中,我在初始化此对象时使用了 final 关键字,因为我知道它会阻止对象引用。但是它解决了我的问题吗?有没有更好的办法?

【问题讨论】:

  • 你可以使用Collections#synchronizedList(List)
  • 请提供正确的示例代码线程应该做什么。您只需发布一堆没有上下文的数据结构。

标签: java multithreading dictionary concurrency parallel-processing


【解决方案1】:

您可以在方法签名中使用synchronised 关键字。当从线程调用synchronised 方法时,它(线程)会自动获取共享对象上的锁。所以你可以做的是使addToQueue方法synchronisedRead more.

或者,检查this。这是Collections.synchronisedList 上的一个信息量很大的线程。也有一个工作的example

【讨论】:

    【解决方案2】:

    我的理解

    1. 每个线程的聚合信息
    2. 在主线程中收集这些聚合数据

    示例代码

    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    
    public class ThreadParallel {
    
        public static void main(String[] args) {
            List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
            class ThreadSpecific {
    
                final String threadName;
                final String num;
    
                ThreadSpecific(int num) {
                    threadName = Thread.currentThread().getName();
                    this.num = Integer.toString(num);
                }
    
                public String getThreadName() {
                    return threadName;
                }
    
                public String getNums() {
                    return num;
                }
            }
    
            Map<String, List<String>> result = input.parallelStream()
                .map(i -> new ThreadSpecific(i))
                .collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
                    Collectors.mapping(ThreadSpecific::getNums, Collectors.toList())));
            System.out.println(result);
        }
    }
    
    

    或者,如果内部聚合对象是列表(或集合),则尝试类似:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    
    public class ThreadParallel {
    
        public static void main(String[] args) {
            List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
            class ThreadSpecific {
    
                final String threadName;
                final List<String> nums;
    
                ThreadSpecific(int num) {
                    threadName = Thread.currentThread().getName();
                    this.nums = new ArrayList<>();
                    nums.add(Integer.toString(num));
                }
    
                public String getThreadName() {
                    return threadName;
                }
    
                public List<String> getNums() {
                    return nums;
                }
            }
    
            Map<String, List<String>> result = input.parallelStream()
                .map(i -> new ThreadSpecific(i))
                .collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
                    Collectors.mapping(ThreadSpecific::getNums,
                        Collectors.collectingAndThen(Collectors.toList(), nums -> nums.stream()
                            .flatMap(List::stream).collect(Collectors.toList())
                    ))));
            System.out.println(result);
        }
    }
    
    

    注意事项

    编辑:在上面的示例中,我在初始化此对象时使用了 final 关键字,因为我知道它会阻止对象引用。但是它解决了我的问题吗?有没有更好的办法?
    引用变量中 final 的目的是 1. 捕获对引用变量的任何意外/意外重新分配(只有引用变量是不可变的) 2. 引用变量的不可变属性确保`L`[123] 缓存在多线程执行中保持该引用变量的一致状态。(可能在多CPU的单线程执行中)。 3.这个特性避免了对`volatile`的需要

    【讨论】:

      猜你喜欢
      • 2011-03-27
      • 2015-02-19
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多