2017-07-09 64 views
1

假設以下簡化示例。設B代表一類處理的一些柵格數據:Java:從Runnable返回結果

import java.awt.image.BufferedImage; 

public class B implements Runnable{ 
    private boolean c; 
    private Runnable f; 

    public B (boolean c_, Runnable f_) { c = c_; f = f_;} 

    public BufferedImage process() { 
      //Some operations 
      BufferedImage output = null; 
      if (c) output = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); 
      return output; 
    } 

    public void run() { process();} 
} 

過程()方法可以但可能不產生輸出評價者。由於計算成本的原因,該過程在單獨的線程中運行。

讓A代表運行過程的類。它也包含了一些後期處理步驟,等到線程完成:

import java.awt.image.BufferedImage; 

public class A { 
    public A(){} 
    public void compute() { 
      boolean c = true; 
      B b = new B(c, new Runnable() { 
        public void run() { 
          //Post process, after the thread has been finished 
          BufferedImage img = ??? //Get resulting raster, how? 
          if (img != null) { 
            //Perform some steps 
          } 
        } 
      }); 

      Thread t = new Thread(b); 
      t.start(); //Run procedure 
    } 
} 

然而,如何讓生成的柵格使用過程()「內的」 運行B的()方法方法中創建一個?

避免模型中,當輸出圖像一起代表B的數據成員與

b.getImage(); 

我看了一則關於回調

Return value from Runnable

但如何在這裏實現它的帖子?感謝您的幫助和簡短的例子。

+2

聽起來像是'Callable'工作。 – Kayaman

+1

你基本上在問:「如何從返回'void'的方法返回一個值?」。所以我想你想要一個'Callable',而不是'Runnable'。 –

+0

它看起來像你傳遞給B的回調,但實際上沒有調用它? (變量'f')你應該在'B'中用'process()'的結果調用'f()'。 – misaka

回答

6

使用ExecutorService,具體地說,它submit(Callable)方法,它返回一個Futureget()isDone()方法可以被調用來檢索結果:

public class B implements Callable<BufferedImage> { 
    private boolean c; 

    public B (boolean c) { this.c = c; } 

    public BufferedImage call() { 
     //Some operations 
     if (!c) 
      return null; 
     return new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); 
    } 
} 

// Somewhere, e.g. in your A.compute() method 

ExecutorService exe = Executors.newFixedThreadPool(2); // Two threads in parallel 
B b = new B(true); 
Future<BufferedImage> res = exe.submit(b); // Will return immediately. Processing will run in a thread of 'exe' executor 
// ... do things 
System.out.println("Finished: "+res.isDone()); 
BufferedImage img = res.get(); // Will block until image is available (i.e. b.call() returns) 

您可以使用ExecutorService不同的口味中,你可以排隊處理這可能(submit(Callable))或不可(execute(Runnable))返回結果。您要使用的Executor類型取決於您需要的處理類型和順序。

+0

@ Matthieu:我可以請你舉個例子嗎? – justik

+0

@justik我更新了一個簡單的例子,有點鏈接到你給的代碼 – Matthieu

+1

這是一個很好的方法,加上一個雖然:) – Yahya

1

你可以嘗試做這樣的事情:

public class B{ 
    private boolean c; 
    volatile boolean finished = false; // it can be shared among threads 
    BufferedImage output; 

    public B (boolean c_) { c = c_;} 

    public void process() { 
     Thread t = new Thread(new Runnable(){ 
      @Override 
      public void run() { 
       if (c) output = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); 
       finished = true; 
      }  
     }); 
     t.start();   
    } 
} 

public class A { 
    public void compute() { 
     B b = new B(true); 
     b.process(); 
     while(!b.finished){System.out.println("Processing");} 
     // when finished check if output is not null 
     // and then do some stuff 
     if(b.output!=null){System.out.println(b.output);} 
    } 
} 
+0

這是重新發明'未來「.. – Matthieu

+0

@Matthieu我從來不知道「未來」,但很高興最終得到的東西有點類似於雅。 – Yahya

+0

@ Yaha:謝謝,但「避免模型,當輸出圖像代表B的數據成員一起......」 – justik