[英]Trying to synchronize method within runnable
我有一個ConcurrentMap,它在我的可運行對象外部實例化,但是在/跨可運行對象內部共享和更新。 我的可運行對象需要是並發的,但是我的current並發地圖更新需要同步,以防止替換先前的條目。 有人可以告訴我我在做什么錯。
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
基於Sotirios Delimanolis,Luiggi Mendoza,Sotirios Delimanolis的解決方案。
主要
public class ExecutionSubmitExample {
public static void main(String[] args) {
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 e = new Example(concurrentMap, x);
Future<Example> future = es.submit(e, e);
tasks.add(future);
}
// -- all threads should be launching, let's get the ExecutionSubmitExample objects
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;
private final Object lock = new Object();
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 void runAnalysis(int index) {
synchronized(lock) {
if(concurrentMap.containsKey(index)) {
System.out.println("contains integer " + index);
} else {
System.out.println("put " + index + " thread " + thread);
concurrentMap.put(index, "thread " + thread);
}
}
}
}
結果
put 0 thread 0
contains integer 0
put 1 thread 7
put 2 thread 7
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
key 0 thread 0
key 2 thread 7
key 1 thread 7
使用ConcurrentMap時應避免同步。 它提供了其他方法來處理這些類型的操作。 對於這種情況,putIfAbsent方法應優先於contains和put方法。
public void runAnalysis(int index) {
if (concurrentMap.putIfAbsent(index, "thread " + thread) == null) {
System.out.println("put " + index + " thread " + thread);
} else {
System.out.println("contains integer " + index);
}
}
如果創建一個新的類“ RunAnalysis”,並在該類中添加方法runAnalysis()的代碼,如下所示:
class RunAnalysis {
public synchronized void analyse(ConcurrentHashMap<Integer, String> concurrentMap, int thread, 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);
}
}
}
public class SyncExample implements Runnable {
RunAnalysis runAnalysis = new RunAnalysis();
ConcurrentHashMap<Integer, String> concurrentMap;
private int thread;
public SyncExample(ConcurrentHashMap<Integer, String> concurrentMap, int thread) {
this.concurrentMap = concurrentMap;
this.thread = thread;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
runAnalysis.analyse(concurrentMap, thread, i);
}
}
}
那么輸出是:
put 0 thread 1
put 1 thread 1
put 2 thread 1
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 0
contains integer 1
contains integer 2
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
contains integer 0
contains integer 1
contains integer 2
key 0 thread 1
key 1 thread 1
key 2 thread 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.