Populating Array from different threads
I'm trying to write a very simple program that creates several threads to send concurrent requests to a particular URL. I measure and store response times. The problem I’m having is that although I create my Response Times array as static and final, the values I store in this array exist only while I am inside of one of my generated threads开发者_如何学JAVA. As soon as I am out of the loop and into the main thread, the array is empty (contains 0 values). So the sum in my code snippet is always zero. I realize that my error is probably a very basic one but unfortunately I was unable to find similar topic online. Could you please point me to the right direction? Thanks.
public class MyClass {
static final long[] respTimes = new long[l];
public static void sendRequest() {...}
public static void main(String[] args) throws Exception {
for(int i=0; i<l; i++) {
new Thread("" + i) {
public void run() {
long startTime = System.nanoTime();
sendRequest();
long estimatedTime = System.nanoTime() - startTime;
respTimes[i] = estimatedTime;
}
}.start();
}
for(int i=0; i<l; i++) { sum += respTimes[i]; }
}
}
That's not the problem. Your problem is that you print out the results before you had a chance to generate them. Do this:
Thread [] theThreads = new Thread[10];
for (...) {
theThreads[i] = new Thread() { ... }.start();
}
// now make sure all the threads are done
for (...) {
// this waits for the thread to finish
theThreads[i].join();
}
// now print things out
Since I have a clinical aversion to static methods :P and a thing for organizing code (Also noticed you didn't handle any exceptions coming out of send method)
public class MultiClient
{
private long[] responseTimes = null;
private Throwable[] errors = null;
public MultiClient(int count)
{
responseTimes = new long[count];
errors = new Throwable[count];
}
protected void sendRequestWrapper(int index)
{
long startTime = System.nanoTime();
try
{
//original send request
sendRequest();
}
// optionally you may put a catch() here to process errors
catch(Throwable t)
{
errors[index] = t;
}
finally
{
//this will guarantee response times filled up even in case of
//sendRequest raising an exception
responseTimes[index] = System.nanoTime() - startTime;
}
}
public void doStuff()
{
Thread[] threads = new Thread[count];
//separete create thread calls
for(int i = 0; i < threads.length; i++)
{
threads[i] = new Worker(i);
}
//... from start calls
for(int i = 0; i < threads.length; i++)
{
threads[i].start();
}
// wait till all threads are done
for(int i = 0; i < threads.length; i++)
{
threads[i].join();
}
}
private class Worker extends Thread
{
private int index = -1;
public Worker(int index)
{
super("worker "+index);
this.index = index;
}
public void run()
{
MultiClient.this.sendRequestWrapper(index);
}
}
public long[] getResponseTimes(){ return responeTimes; }
public Throwable[] getErrors(){ return errors; }
public boolean sendFailed(int indeX){ return errors[index] != null; }
public static void main(String[] args)
{
int count = ...; // get count from somewhere (cmd line, hard coded etc.)
MultiClient multiClient = new MultiClient(count); //create an array filler
multiClient.doStuff(); //this will block till all the threads are done
long[] responseTimes = multiClient.getResponseTimes();
//do whatever you want with the response times
}
}
You are probably experiencing a race condition. The for loop is completed before any of the threads have actually started and/or finished.
If you are using JDK 1.5 or higher, look into using the java.lang.concurrent classes. They make these types of thread joining operations quite easy.
精彩评论