Link to home
Start Free TrialLog in
Avatar of jhughes4
jhughes4

asked on

Writing to an Array from within individual Threads

In the example below I would like to be able to have multiple threads write to a single ArrayList that would be accessible by main once all threads had completed.  How could I do this with the sample provided?  Thanks in advance.

public class MyThread implements Runnable {
  private String input;
  public int output;
ArrayList newArrayList = new ArrayList();

  public MyThread(String s) {
    input = s;
  }

  public void run() {
    test(input);
  }
}


public class ThreadTest {

  public static void main(String args[]) {

    MyThread my = new MyThread("hello");
    Thread t = new Thread(my);
    t.start();



    try {
      t.join();
//how could I get the results of multiple threads here????
    } catch (InterruptedException e) {}



  }

static synchronized void test(String in) {
newArrayList .add("hello");  //HERE'S WHERE I WOULD LIKE TO ADD THE RESULTS TO AN ARRAY THAT WOULD BE ACCESSIBLE BY MAIN ONCE THE THREADS ARE DONE.


}
Avatar of Mick Barry
Mick Barry
Flag of Australia image

You need to declare newArrayList as static, and add a static member variable to give access to it
Avatar of aozarov
aozarov

Or you can define newArrayList as the main local variable and pass it to your Threads.
e.g.


public class MyThread implements Runnable {
  private String input;
  public int output;
  ArrayList list;

  public MyThread(String s, ArrayList givenList) {
    input = s;
    list = givenList
  }

  public void run() {
    // you can use list here
    test(input);
  }
}


public class ThreadTest {

  public static void main(String args[]) {
    ArrayList newArrayList  = new ArrayList();
    newArrayList.add("hello");  //HERE'S WHERE I WOULD LIKE TO ADD THE RESULTS TO AN ARRAY THAT WOULD BE ACCESSIBLE BY MAIN ONCE
    MyThread my = new MyThread("hello", newArrayList);
    Thread t = new Thread(my);
    t.start();

    try {
      t.join();
//how could I get the results of multiple threads here????
    } catch (InterruptedException e) {}

  }

}
This way is making it really accesible only to the main method and to any object you pass it as an argument (as you specified).
Having it as static member will expose it to any static and non static method of that class.
You should bare in mind though that ArrayList is NOT thread safe.
so in case of multiple threads accessing/modifying it you will need to either synchronized the access to it or use Vector instead.
if you want to dispatch multiple Threads you can do it this way:

public static void main(String args[]) {
    ArrayList newArrayList  = new ArrayList();
    newArrayList.add("hello");  //HERE'S WHERE I WOULD LIKE TO ADD THE RESULTS TO AN ARRAY THAT WOULD BE ACCESSIBLE BY MAIN ONCE
    Thread[] threads = new Thread[<pick_here_the_number_of_threads>];
    for (int i = 0; i < threads.length; i++)
    {
        MyThread my = new MyThread("hello", newArrayList);
        Thread t = new Thread(my);
        t.start();
        threads[i] = t;
    }


    try {
      for (int i = 0; i < threads.length; i++)
               threads[i].join();
    } catch (InterruptedException e) {}
   
     // here you can get the results of  newArrayList
 ...
}
> You should bare in mind though that ArrayList is NOT thread safe.

The existing method being used is already thread safe.
>> The existing method being used is already thread safe.
How come if he wants to have mutliple threads to access the same list? "how could I get the results of multiple threads here????"
As I already explained in my original comment
jhughes4, with the method I suggested you (to pass the List to the threads in the constructor instead of using static variable) you
will be better of doing this (for thread safety):

    ArrayList newArrayList  = new ArrayList();
    List list = Collections.synchronizedList(newArrayList);

    Thread[] threads = new Thread[<pick_here_the_number_of_threads>];
    for (int i = 0; i < threads.length; i++)
    {
        MyThread my = new MyThread("hello", list);
        Thread t = new Thread(my);
        t.start();
        threads[i] = t;
    }
Though your existing code is already threadsafe :)



But also your existing code enable any class in the same packae to call this method. so it is not visible only to the main
method and to the threds it creats.
Having it the way I suggest gives you both
If there is only one thread accessing the list at a time (which is the case with the current code) then synchronizing it is unnecessary overhead.
Though the code has only one thread the request was for "would like to be able to have multiple threads write to a single ArrayList "
I assumed that also part of the question is how to create and wait for multiple threads and provided him with a solution for that as well.
The existing code is already thread-safe regardless of how many processing threads are added.
To add extra processing threads all that is needed is to start additional threads the same way the current one is started.
Once all the processing threads have completed processing the list is only being access by a single thread.
>> To add extra processing threads all that is needed is to start additional threads the same way the current one is started.
I saw this message "//how could I get the results of multiple threads here????"
and assumed the jhughes4 needs help with invoking and waiting for *multiple threads* so I showed him how this can be done,
is there anything wrong with that??
Of course not, but your suggesting the existing code is not thread safe which is all I am clarifying that it is threadsafe. The number of threads that is started, whether it is 1 or 100 is irrelevant to how safe it is. And jhughes4 knows how to start one thread so one would assume that starting others is not a problem, just needs a means to access the list once the processing has completed.
Anyways all I wanted to point out was that the existing code is already thread safe.
>>  but your suggesting the existing code is not thread safe which is all I am clarifying that it is threadsafe.
I had no such suggestion I was refering to my original code and there after I provided a fix for it.

>> And jhughes4 knows how to start one thread so one would assume that starting others is not a problem
I prefer not to assume that because of the multiple join and because of his remark which I mentioned above.

The only thing I am suggesting about the original code is that any class in the package can access that method and
I am not sure if that is what he wants and for his original code to compile successfuly he has to have MyThread in the same
package as ThreadTest
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jhughes4

ASKER

First of all thanks to both of you for your dedication to my question.  Both solutions were helpful to me.  Thanks again.
:-)