java并发问题

时间:2011-07-31 16:30:06

标签: java multithreading concurrency

我想使用CPU的两个内核对矢量(数组)进行简单的数学运算。该程序无法正常工作。请解释我如何解决我的问题。

public class MyRunnable implements Runnable {

private int startIndex;
private int endIndex;
private float[] tab;

public MyRunnable(int startIndex, int endIndex, float[] tab)
{
    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.tab = tab;
}

@Override
public void run() 
{
    System.out.println(Thread.currentThread());
    for(int i = startIndex; i < endIndex; i++)
    {
        tab[i] = i * 2;
    }

    System.out.println("Finished");
}

}

public class Test {

public static void main(String[] args) {

    int size = 10;
    int n_threads = 2;
    float tab[] = new float[size];

    for(int i = 0; i < size; i++)
    {
        tab[i] = i;
    }

    System.out.println(Thread.currentThread());

    for(int i = 0; i < size; i++)
    {
        System.out.println(tab[i]);
    }

    Runnable r1 = new MyRunnable(0, size / n_threads, tab );
    Runnable r2 = new MyRunnable(size / n_threads, size, tab );

    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();

    for(int i = 0; i < size; i++)
    {
        System.out.println(tab[i]);
    }

}

3 个答案:

答案 0 :(得分:2)

好像你不等待线程完成。使用join方法并添加

t1.join();
t2.join();

就在输出循环之前。

答案 1 :(得分:2)

正如其他人所指出的,你不是在等待你的线程完成执行。您应该遵循@Howard和@JK的建议,这将解决您的基本问题。如果您决定使用线程和并行处理做更多事情,虽然我强烈建议查看java.util.concurrent包 - 它们有许多有用的类,可以让您的生活更轻松。

我冒昧地使用Callable和ExecutorService重新编码您的示例。请参阅下面的示例代码:

public static void main(String[] args) {

    int size = 10;
    int n_threads = 2;
    float tab[] = new float[size];

    for (int i = 0; i < size; i++) {
        tab[i] = i;
    }

    System.out.println(Thread.currentThread());

    for (int i = 0; i < size; i++) {
        System.out.println(tab[i]);
    }

    // Determine batch size, based off of number of available
    // threads.
    int batchSize = (int) Math.ceil((double) size / n_threads);
    System.out.println("Size: " + size + " Num threads: " + n_threads
            + " Batch Size: " + batchSize);

    // Create list of tasks to run
    List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(
            n_threads);

    for (int i = 0; i < n_threads; i++) {
        tasks.add(Executors.callable(new MyRunnable(i * batchSize,
                ((i + 1) * batchSize) - 1, tab)));
    }

    // Create an executor service to handle processing tasks
    ExecutorService execService = Executors.newFixedThreadPool(n_threads);

    try {
        execService.invokeAll(tasks);
    } catch (InterruptedException ie) {
        ie.printStackTrace();
} finally {
    execService.shutdown();
}

    for (int i = 0; i < size; i++) {
        System.out.println(tab[i]);
    }
}

在你的MyRunnable类中做了一个小改动,它正在跳过最后一个索引的处理:

@Override
public void run() {
    System.out.println(Thread.currentThread());
    for (int i = startIndex; i <= endIndex; i++) {
        tab[i] = i * 2;
    }

    System.out.println("Finished");
}

效果很好,你可以自己测试一下。 java.util.concurrent中还有更多可以执行类似功能的类,可以随意浏览。

祝你好运!

答案 2 :(得分:1)

您可以通过插入Thread.join()的调用来等待线程完成执行:

t1.join();
t2.join();

x.start()函数调用后暂停,直到线程完成。否则你无法知道它们是否已经完成执行。

您还应该考虑将单独线程中的tab[]访问与mutex/semaphore or similar mechanism同步,而不必直接对传入的数组引用执行计算,因为这会限制并发数量(如果本)。