2012-06-05 116 views
1

同步我采取的是计算Julia集的程序。它将使用多个线程,具体取决于可用的处理器数量。每个线程计算一条线,但只有当该线不被另一个线程计算时。这部分工作得很好。多线程安全在Java

但有时,当我测试它与更大的图像(更多的线来计算,例如而不是getHeight() = 1200,我把它设置为3000,有一些行被跳过)。我想让它更安全,这样不会有两行计算,也不会跳过任何行。这里是run()方法的代码:我希望它这样的工作

public void run() { 
    while (counter < getHeight()-1) { 
     synchronized(this) { 
      if (counter >= getHeight() -1) { //so that the last line will not be calculated >2 times. 
       return; 
      } 
      counter++; 
      image.setRGB(0, counter, getWidth(), 1, renderLine(counter), 0, 0); 
     } 
    } 
    } 

:如果所计算的当前行,线程便进入到下一行..不,它感到困惑,使线得到跳过..

我想这其实:

public void run() { 
    while (counter < getHeight()-1 && !working) { 
     synchronized(this) { 
      working = true; 
      if (counter >= getHeight() -1) { //so that the last line will not be calculated >2 times. 
       return; 
      } 
      counter++; 
      image.setRGB(0, counter, getWidth(), 1, renderLine(counter), 0, 0); 
      working = false; 
     } 
    } 
    } 

,但是,我不知道这是否会阻止访问到另一个线程当某个线程已经工作,它将改变值“counter”,这意味着行可以跳过!

我需要一个布尔变量来通知线程实际工作的一条线吗?有什么建议?

+0

的方法run u可以有一个数组表示已经获得的线的数量。但如果线数增加,肯定会使应用程序变慢。 – Asif

回答

5

你几乎可以肯定做得太多自己的线程管理。使用ExecutorService可以在多个线程之间分配工作而不会有重复。

ExecutorService service = Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors()); 
for (int row = minRow; row <= maxRow; row++) { 
    service.submit(new FillThisRowRunnable(row)); 
} 
+0

我不能。它是一门功课,我们不应该用别的除了“同步”和“简单”的方法和修饰:-),我已经处理器=调用Runtime.getRuntime()availableProcessors())。作为我班的对象变量。我只是通过计算图像的线条来处理更多的安全问题。正如我所说,它现在工作很好,但如果有人有任何建议,它会更安全,这将是非常有益的..谢谢! – ZelelB

+0

如果是家庭作业,应该使用[作业]标签进行标记。 –

+1

ooopss!对不起Louis!现在完成! – ZelelB

1

你真的需要为所有线程的共享对象。该对象将告诉其他线程处理哪一行。

我不能肯定的告诉你现在有什么,但似乎每个​​是在你失去所有相互排斥的不同实例。请记住,当同步发生在共享对象上时,同步仅适用于多个线程,否则每个线程将在线程本地对象上同步,其中没有任何内容可以实现。

下面是一个例子

public class SharedLineCounter{ 
    private final int maxNumberOfLines; 
    private int currentLineNumber =0; 
    public SharedLineCounter(int maxNumberOfLines){ 
     this.maxNumberOfLines = maxNumberOfLines; 
    } 
    public synchronized int getNextLine(){ 
     if(++currentLineNumber > maxNumberOfLines) 
     return -1; //end case 
     return currentLineNumber ; 
    } 
} 

public class WorkerThread extends Thread{ 
    private final SharedLineCounter counter; 
    public WorkerThread(SharedLineCounter counter){ 
     this.counter = counter; 
    } 
    public void run(){ 
     int next = -1; 
     while((next = counter.getNextLine()) >= 0){ 
     image.setRGB(0, next , getWidth(), 1, renderLine(next), 0, 0); 
     } 
    } 
    } 
} 

这里每个线程将共享此线程安全线计数器,以便每个线程应该总是让一个独特的和连续的行号。

编辑回答你的问题:

可以使线程匿名通过共享的全局实例

public static void main(String args[]){ 
    final SharedCounter counter = new SharedCounter(); 

    Thread worker1 = new Thread(new Runnable(){ 
     public void run(){ 
      counter.getNextLine(); //etc 
     } 
    }); 
    Thread worker2 = new Thread(new Runnable(){ 
     public void run(){ 
      counter.getNextLine(); //etc 
     } 
    }); 

} 

一个警告,以解决基于您的评论。您应该通过new Runnable并创建一个匿名可运行的,它的坏习惯子类和覆盖Thread

+0

感谢您的回答! 好的,教授给了我们同一班,但只使用一个处理器。所以我们可以比较我们的结果,如果它是禁食的,例如,如果我有4个处理器,使用多线程,它应该快4倍。虽然我的同步程序正在做某些事,因为如果你的速度比他的班级快4倍(只使用一个没有线程的处理器),当我告诉我时,我评论了我的同步块,它仍然运行得更快4倍! O_o 所以是的,它没有做任何事情,但是它怎么会比他的班级跑4倍? – ZelelB

+0

对不起ZelelB我遇到了麻烦。哪个班级的共享计数器或没有共享计数器的哪个班级速度快4倍? –

+0

我发布的一个..但没有“同步”其工作4倍快,图像是好的! (没有线路跳过) – ZelelB