当前位置: 首页 > 面试题库 >

尝试在runnable中同步方法

鱼征
2023-03-14
问题内容

我有一个ConcurrentMap,它在我的可运行对象外部实例化,但是在/跨整个可运行对象内部共享和更新。我的可运行对象需要是并发的,但是我的currentMap的更新需要同步,以防止替换先前的条目。有人可以告诉我我在做什么错。

public class ExecutionSubmitExample {

    public static void main(String[] args) {
        //Ten concurrent threads
        ExecutorService es = Executors.newFixedThreadPool(10);

        List<Future<Example>> tasks = new ArrayList<>();

        ConcurrentHashMap<Integer, String> concurrentMap = new ConcurrentHashMap<>();

        for (int x = 0; x < 10; x++) {
            Example example = new Example(concurrentMap, x);
            Future<Example> future = es.submit(example, example);
            tasks.add(future);
        }

        try {
            for (Future<Example> future : tasks) {
                Example e = future.get();
            }

            for (Entry<Integer,String> obj : concurrentMap.entrySet()) {
                System.out.println("key " + obj.getKey() + " " + obj.getValue());
            }
            es.shutdown();
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException ie) {
            throw new RuntimeException(ie);
        }
    }
}

可运行

public class Example implements Runnable {

    ConcurrentHashMap<Integer, String> concurrentMap;
    private int thread;

    public Example(ConcurrentHashMap<Integer, String> concurrentMap, int thread) {
        this.concurrentMap = concurrentMap;
        this.thread = thread;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            runAnalysis(i);
        }
    }

    public synchronized void runAnalysis(int index) {
        if(concurrentMap.containsKey(index)) {
            System.out.println("contains integer " + index);
        } else {
            System.out.println("put " + index + " thread " + thread);
            concurrentMap.put(index, "thread " + thread);
        }
    }
}

结果 -注意索引0被添加多次而不是一次。它应该由线程0添加,并由线程9读取。我不知何故需要将该方法与其他线程锁定,直到更新完成。

put 0 thread 0
put 0 thread 9
put 0 thread 6
put 0 thread 7
put 1 thread 7
put 0 thread 2
put 0 thread 1
put 0 thread 5
put 0 thread 3
put 0 thread 4
contains integer 1
contains integer 1
contains integer 1
contains integer 1
put 2 thread 7
put 1 thread 6
put 1 thread 9
put 1 thread 0
put 0 thread 8
contains integer 2
contains integer 2
contains integer 2
put 2 thread 2
put 2 thread 1
put 2 thread 5
put 2 thread 3
contains integer 1
contains integer 1
contains integer 2
contains integer 2
key 0 thread 8
key 2 thread 3
key 1 thread 0

问题答案:

synchronized在方法上意味着synchronizedthis对象上。由于您每次都在创建新对象

Example example = new Example(concurrentMap, x);

同步发生在不同的对象上,因此没有阻塞。

您需要synchronized使用共享对象或使用共享对象Lock。这些可以传递给Example对象,也可以使用Luiggi建议的static字段。在这种情况下,请注意该字段不会在其他任何地方同步,否则可能会干扰此执行。



 类似资料:
  • 问题内容: 我正在查看包含同步方法的第三方库中的一些代码,在此方法中,有一个锁定在实例变量上的同步块。与此类似: 这有意义吗?如果是这样,在同步方法中使用同步语句有什么好处? 鉴于同步方法锁定了整个对象,对我来说似乎是多余的。在使用非私有的实例变量时,这种方法是否有意义? 问题答案: 在您的示例中,该方法 同时 锁定了和的实例。其他方法可能仅锁定对象的实例 或 对象。 因此,是的,这完全取决于他们

  • 尝试在IntelliJ中构建我的第一个helloWorld程序时遇到以下同步错误。 我第一次在运行Windows 10的计算机上安装了IntelliJ。

  • 假设我在某个类上有一个同步方法: 我在不使用同步修饰符的情况下覆盖了它: 关于这个场景,我有几个具体的问题: 重写的方法也会隐式同步吗? 如果没有,-call会同步吗? 如果没有-call,会同步任何东西吗? 有没有办法强制覆盖方法使用(我注意到抽象方法定义或接口内的方法定义不允许同步关键字)?

  • 请看下面给我带来麻烦的方法: 然后是run方法:

  • 问题内容: 我不确定这是否是同步我的的正确方法。 我有一个 从函数传递过来的。 现在,我正在尝试使其同步。这是否正确同步了我的对象? 问题答案: 您要进行两次同步,这是没有意义的,可能会减慢代码的速度:在列表上进行迭代时所做的更改需要整个操作的同步,在这种情况下,使用Using 这样做是多余的(它创建了一个包装程序来同步各个操作)。 但是,由于您要完全清空列表,因此迭代删除第一个元素是最糟糕的方法

  • 我正在与async Wait try catch块斗争几天。 这个异步函数中的try-catch是否正确? 这就是我创建自定义错误类并全局导出的方式。 要求: 故意换了工作。我想找份工作。国际直拨电话 这样我就能抓住错误。如果有错误,则抛出新创建的自定义错误类。但抛出队列错误将导致日志记录 同样,即使不需要捕捉那个里的错误,因为try块在工作,若我抛出QueueError,我只想捕捉最后一个cat