Reputation: 95
How do I create a common variable between threads? For example: Many threads sending a request to server to create users.
These users are saved in an ArrayList
, but this ArrayList
must be synchronized for all threads. How can I do it ?
Thanks all!
Upvotes: 0
Views: 563
Reputation: 533510
I would use an ExecutorService
and submit tasks to it you want to perform. This way you don't need a synchronized collection (possibly don't need the collection at all)
However, you can do what you suggest by creating an ArrayList wrapped with a Collections.synchronizedList()
and pass this as a reference to the thread before you start it.
What you could do is something like
// can be reused for other background tasks.
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
List<Future<User>> userFutures = new ArrayList<>();
for( users to create )
userFutures.add(executor.submit(new Callable<User>() {
public User call() {
return created user;
}
});
List<User> users = new ArrayList<>();
for(Future<User> userFuture: userFutures)
users.add(userFuture.get();
Upvotes: 2
Reputation: 116878
To expand on @Peter's answer, if you use an ExecutorService
you can submit a Callable<User>
which can return the User
that was created by the task run in another thread.
Something like:
// create a thread pool with 10 background threads
ExecutorService threadPool = Executors.newFixedThreadPool(10);
List<Future<User>> futures = new ArrayList<Future<User>>();
for (String userName : userNamesToCreateCollection) {
futures.add(threadPool.submit(new MyCallable(userName)));
}
// once you submit all of the jobs, we shutdown the pool, current jobs still run
threadPool.shutdown();
// now we wait for the produced users
List<User> users = new ArrayList<User>();
for (Future<User> future : futures) {
// this waits for the job to complete and gets the User created
// it also throws some exceptions that need to be caught/logged
users.add(future.get());
}
...
private static class MyCallable implements Callable<User> {
private String userName;
public MyCallable(String userName) {
this.userName = userName;
}
public User call() {
// create the user...
return user;
}
}
Upvotes: 1
Reputation:
If you are going to access the list from multiple threads, you can use Collections to wrap it:
List<String> users = Collections.synchronizedList(new ArrayList<String>());
and then simply pass it in a constructor to the threads that will use it.
Upvotes: 4