英文:
How to use ConcurrentHashMap in a MultiThread application with Callable
问题
我想创建一个多线程应用程序,并使用Callable接口,但我希望所有线程同时在ConcurrentHashMap中添加一些值,并在程序结束时打印带有结果的哈希映射。
更具体地说,我有一个包含一些名称的列表。我遍历列表并结合线程,对于每个线程,如果名称的长度小于5,则希望将其添加到并发哈希映射中。
在程序结束时,我希望打印所有名称长度小于5的并发哈希映射。
所以我的主类如下:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AddElementsToMap {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
List<String> list = new ArrayList<String>();
list.add("Dimitrios");
list.add("Maria");
list.add("Jason");
list.add("Io");
list.add("Jessica");
ExecutorService executor = Executors.newFixedThreadPool(3);
ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();
for (String name : list) {
Future future = executor.submit(new AddElementsToMapCallable(name, map));
futureList.add(future);
}
executor.shutdown();
System.out.println("MAP " + map);
}
}
和我的Callable如下:
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
public class AddElementsToMapCallable implements Callable {
private String name;
private String className;
ConcurrentHashMap<String, String> map;
public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {
this.className = this.getClass().getSimpleName();
this.name = name;
this.map = map;
}
@Override
public Object call() throws Exception {
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId() + " Processing User = " + name);
if (name.length() <= 5) {
System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is smaller than 5. Adding!");
map.put(name, String.valueOf(name.length()));
} else {
System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is BIGGER than 5");
}
return map;
}
public long getThreadId() {
return Thread.currentThread().getId();
}
public Thread getThread() {
return Thread.currentThread();
}
}
但是我得到的结果不是我想要的...
MAP {}
AddElementsToMapCallablecall ThreadID = 14 Processing User = Maria
AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrios
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jason
AddElementsToMapCallablecall ThreadID = 14 Processing User = Marialength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrioslength is BIGGER than 5
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jasonlength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 15 Processing User = Io
AddElementsToMapCallablecall ThreadID = 15 Processing User = Iolength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessica
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessicalength is BIGGER than 5
有人能帮助我吗?我做错了什么?谢谢!
英文:
I want to have a threading application and I use Callable interface, but I want all the threads to add simultaneously in a ConcurrentHashmap some values, and at the end of the program to print the hashmap with the results.
More specifically, I have a list with some names. I iterate through the list and combine threading and in each thread if the name's length is shorter than 5 , then I want it added to the concurrent hashmap.
At the end of the program I want to print the concurrent hashmap with all the names that are shorter than 5.
So my main class is the following:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AddElementsToMap {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
List<String> list = new ArrayList<String>();
list.add("Dimitrios");
list.add("Maria");
list.add("Jason");
list.add("Io");
list.add("Jessica");
ExecutorService executor = Executors.newFixedThreadPool(3);
ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();
for (String name : list) {
Future future = executor.submit(new AddElementsToMapCallable(name, map));
futureList.add(future);
}
executor.shutdown();
System.out.println("MAP " + map);
}
}
and My Callable is the following
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
public class AddElementsToMapCallable implements Callable {
private String name;
private String className;
ConcurrentHashMap<String, String> map;
public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {
this.className = this.getClass().getSimpleName();
this.name = name;
this.map = map;
}
@Override
public Object call() throws Exception {
HashMap<String, String> map = new HashMap<String, String>();
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId() + " Processing User = " + name);
if (name.length() <= 5) {
System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is smaller than 5. Adding!");
map.put(name, String.valueOf(name.length()));
} else {
System.out.println(className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is BIGGER than 5");
}
return map;
}
public long getThreadId() {
return Thread.currentThread().getId();
}
public Thread getThread() {
return Thread.currentThread();
}
}
but what I get as a result is as you can see not what I wanted...
MAP {}
AddElementsToMapCallablecall ThreadID = 14 Processing User = Maria
AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrios
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jason
AddElementsToMapCallablecall ThreadID = 14 Processing User = Marialength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 13 Processing User = Dimitrioslength is BIGGER than 5
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jasonlength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 15 Processing User = Io
AddElementsToMapCallablecall ThreadID = 15 Processing User = Iolength is smaller than 5. Adding!
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessica
AddElementsToMapCallablecall ThreadID = 15 Processing User = Jessicalength is BIGGER than 5
Could someone help me? What am I doing wrong??
Thanks !
答案1
得分: 1
构造函数中传递的map
变量和call
方法的第一行存在作用域问题。如果您想将条目添加到构造函数中传递的Map中,可以尝试类似以下的方式:
public class AddElementsToMap {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
List<String> list = new ArrayList<String>();
list.add("Dimitrios");
list.add("Maria");
list.add("Jason");
list.add("Io");
list.add("Jessica");
ExecutorService executor = Executors.newFixedThreadPool(3);
ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();
for (String name : list) {
Future future = executor.submit(new AddElementsToMapCallable(name, map));
futureList.add(future);
}
// Wait until all threads are finished (Hopefully this is just for a learning experience)
try {
for (Future f : futureList) {
f.get();
}
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace(System.err);
}
executor.shutdown();
System.out.println("MAP " + map);
}
static class AddElementsToMapCallable implements Callable {
private String name;
private String className;
ConcurrentHashMap<String, String> map;
public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {
this.className = this.getClass().getSimpleName();
this.name = name;
this.map = map;
}
@Override
public Object call() throws Exception {
// 移除此行。这个map会遮蔽构造函数中传递的map
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name);
if (name.length() <= 5) {
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + " length is smaller than 5. Adding!");
map.put(name, String.valueOf(name.length()));
} else {
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + " length is BIGGER than 5");
}
return map;
}
public long getThreadId() {
return Thread.currentThread().getId();
}
public Thread getThread() {
return Thread.currentThread();
}
}
}
英文:
Scope issue of map
variable passed in the constructor and the first line of method call
. If you want to add the entries into the Map passed in the constructor you can try something like this:
public class AddElementsToMap {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
List<String> list = new ArrayList<String>();
list.add("Dimitrios");
list.add("Maria");
list.add("Jason");
list.add("Io");
list.add("Jessica");
ExecutorService executor = Executors.newFixedThreadPool(3);
ArrayList<Future<Object>> futureList = new ArrayList<Future<Object>>();
for (String name : list) {
Future future = executor.submit(new AddElementsToMapCallable(name, map));
futureList.add(future);
}
// Wait until all threads are finished (Hopefully this is jsut for a learning experience)
try {
for (Future f : futureList) {
f.get();
}
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace(System.err);
}
executor.shutdown();
System.out.println("MAP " + map);
}
static class AddElementsToMapCallable implements Callable {
private String name;
private String className;
ConcurrentHashMap<String, String> map;
public AddElementsToMapCallable(String name, ConcurrentHashMap<String, String> map) {
this.className = this.getClass().getSimpleName();
this.name = name;
this.map = map;
}
@Override
public Object call() throws Exception {
HashMap<String, String> map = new HashMap<String, String>(); // REMOVE this line. This map will shadow the map passed in the constructor
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name);
if (name.length() <= 5) {
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is smaller than 5. Adding!");
map.put(name, String.valueOf(name.length()));
} else {
System.out.println(
className + "call" + " ThreadID = " + Thread.currentThread().getId()
+ " Processing User = " + name + "length is BIGGER than 5");
}
return map;
}
public long getThreadId() {
return Thread.currentThread().getId();
}
public Thread getThread() {
return Thread.currentThread();
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论