简体   繁体   English

使用 ConcurrentHashMap 和同步块的 Java 并发

[英]Java concurrency using ConcurrentHashMap with synchronized block

Here is my main class that initializes and starts 5 different Threads:这是我的主类,它初始化并启动 5 个不同的线程:

public class Server implements Runnable {
    Server1 server1;
    Thread server1Thread;

    public Server() {}

    @Override
    public void run() {
        server1 = new Server1();
        server1Thread = new Thread(server1);
        server1Thread.start();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Server s = new Server();
            s.run();
        }
    }
}

Here is my Server1 Runnable:这是我的Server1 Runnable:

import java.util.concurrent.ConcurrentHashMap;
public class Server1 implements Runnable {
    private ConcurrentHashMap<Integer, Integer> storage= new ConcurrentHashMap<>();

    public Server1() {}

    @Override
    public void run() {
        synchronized (this){
            for (int i = 0; i < 10; i++) {
                storage.put(i, (int)(Math.random()*100));
            }
            for (int i : storage.keySet()) {
                System.out.print("(" + i + "," + storage.get(i) + ") ");
            }
            System.out.println();
        }
    }
}

It puts in ConcurrentHashMap storage keys from 0 to 9 and assigns them a random value between 0 and 100 .它放入ConcurrentHashMap storage键从09并为它们分配一个0100之间的随机值。 After that it prints it and prints new line at the end.之后它打印它并在最后打印新行。 I have user synchronized block to make sure the thread itself access keys correctly but it prints something like this:我有用户synchronized块以确保线程本身正确访问密钥,但它打印如下内容:

(0,8) (0,87) (1,60) (1,14) (2,20) (2,70) (3,5) (0,74) (0,42) (1,22) (4,96) (0,85) (1,97) (2,75) (3,68) (4,3) (5,49) (6,3) (7,9) (8,47) (9,52) 
(3,2) (5,74) (2,86) (1,48) (3,5) (6,0) (4,0) (7,86) (4,22) (8,20) (2,17) (9,87) 
(5,96) (5,15) (6,15) (6,92) (7,48) (8,93) (9,67) 
(3,87) (7,43) (4,34) (5,48) (8,91) (9,64) 
(6,84) (7,75) (8,47) (9,87) 

which obviously means that some thread prints more that 10 keys that I assigned to it.这显然意味着某些线程打印了我分配给它的 10 个以上的键。 How do I make every thread print exactly 10 keys and values that it is assigned to them and ensure concurrency here?如何让每个线程准确打印分配给它们的 10 个键和值并确保这里的并发性?

I am not sure how to test it.我不知道如何测试它。

Your threads don't share any internal state.您的线程不共享任何内部状态。 They're working fine, but the output is interleaved.他们工作正常,但输出是交错的。

For instance if you used a StringBuilder to do the I/O in one operation, you should see correct output.例如,如果您使用StringBuilder在一个操作中执行 I/O,您应该会看到正确的输出。

        StringBuilder buff = new StringBuilder();
        for (int i : storage.keySet()) {
            buff.append("(" + i + "," + storage.get(i) + ") ");
        }
        System.out.println(buff);

There is no good reason for Server to be Runnable , or even to create any instances of it.没有充分的理由让Server成为Runnable ,甚至创建它的任何实例。

You do not share any of the maps.您不共享任何地图。 If you did, then you would also want to share a common lock, but this is not the usual way to use ConcurrentMap .如果您这样做了,那么您还希望共享一个公共锁,但这不是使用ConcurrentMap的常用方法。

All you had to do was synchronized (Server1.class) as that is common across threads.您所要做的就是synchronized (Server1.class)因为这在线程间很常见。 Not the instance不是instance

Here is the verified output:这是经过验证的输出:

(0,75) (1,9) (2,61) (3,73) (4,55) (5,34) (6,34) (7,74) (8,41) (9,0) (0,75) (1,9) (2,61) (3,73) (4,55) (5,34) (6,34) (7,74) (8,41) (9,0)

(0,30) (1,42) (2,46) (3,66) (4,12) (5,17) (6,62) (7,59) (8,74) (9,4) (0,30) (1,42) (2,46) (3,66) (4,12) (5,17) (6,62) (7,59) (8,74) (9,4)

(0,50) (1,16) (2,29) (3,74) (4,68) (5,42) (6,33) (7,91) (8,25) (9,7) (0,50) (1,16) (2,29) (3,74) (4,68) (5,42) (6,33) (7,91) (8,25) (9,7)

(0,49) (1,10) (2,39) (3,94) (4,12) (5,55) (6,54) (7,89) (8,21) (9,75) (0,49) (1,10) (2,39) (3,94) (4,12) (5,55) (6,54) (7,89) (8,21) (9,75)

(0,77) (1,10) (2,37) (3,32) (4,73) (5,39) (6,64) (7,98) (8,96) (9,44) (0,77) (1,10) (2,37) (3,32) (4,73) (5,39) (6,64) (7,98) (8,96) (9,44)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM