2011-07-31 72 views
-1

我想使用我的CPU的兩個核心在矢量(數組)上進行簡單的數學運算。該程序無法正常工作。請解釋我如何解決我的問題。java併發問題

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

}

+1

你應該添加什麼不起作用的確切細節〜! – gideon

+1

你是什麼意思「不正常工作」? – Howard

+0

你期望這個程序做什麼,它做什麼呢? –

回答

1

您可以等待線程插入調用完成執行到Thread.join():你x.start()函數調用來暫停,直到後

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

線程已完成。否則,你無法知道它們是否完成執行。

您還應該考慮將單獨線程中的tab[]訪問與mutex/semaphore or similar mechanism同步,並且不一定直接對傳入的數組引用執行計算,因爲這會限制併發量(如果存在)。

2

看起來好像你不等待線程完成。使用join方法並在輸出循環之前添加

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

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中有更多的類可以完成類似的功能,可以隨時進行探索。

祝你好運!

+0

我相信最後的索引是有意跳過的(他用開始包容/結束排他) –

+0

呃不,他沒有。他在整個代碼中保留從0開始的索引 –

+0

您可以保留新的MyRunnable(i * batchSize,(i + 1)* batchSize,tab))'而不是您所做的事情(使得它更具可讀性用於包括startindex和結束索引在內) –