0

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!

3
  • 4
    Create the variable. Pass it as an argument to the Thread (you should use Runnable) constructor. Commented Sep 9, 2013 at 13:58
  • Umh, ok. In a Server class (when create a thread, i pass all common variable, right?). For example, the ArrayList USERS is a static variable in the Server.java. In main, i create Thread with USERS as thread's argument. Commented Sep 9, 2013 at 14:00
  • Yes, that is one way of doing it. Commented Sep 9, 2013 at 14:04

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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();

2 Comments

+1 because it may help to avoid synchronized at all. Which is a good, good, good thing to start with.
I think the collection is still necessary because at the end he wants a list of them.
1

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;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.