2016-02-27 77 views
0

我從Java教程oracle看到了下面的代碼。我的問題是,ForkBlur.compute()方法如何以及在哪裏調用?我沒有看到任何對ForkBlur.compute()的調用,但是這個方法確實被執行了。有什麼我失蹤?在哪裏以及如何調用ForkBlur.compute()方法?

import java.awt.image.BufferedImage; 
import java.io.File; 
import java.util.concurrent.ForkJoinPool; 
import java.util.concurrent.RecursiveAction; 
import javax.imageio.ImageIO; 

/** 
* ForkBlur implements a simple horizontal image blur. It averages pixels in the 
* source array and writes them to a destination array. The sThreshold value 
* determines whether the blurring will be performed directly or split into two 
* tasks. 
* 
* This is not the recommended way to blur images; it is only intended to 
* illustrate the use of the Fork/Join framework. 
*/ 
public class ForkBlur extends RecursiveAction { 

    private int[] mSource; 
    private int mStart; 
    private int mLength; 
    private int[] mDestination; 
    private int mBlurWidth = 15; // Processing window size, should be odd. 

    public ForkBlur(int[] src, int start, int length, int[] dst) { 
     mSource = src; 
     mStart = start; 
     mLength = length; 
     mDestination = dst; 
    } 

    // Average pixels from source, write results into destination. 
    protected void computeDirectly() { 
     int sidePixels = (mBlurWidth - 1)/2; 
     for (int index = mStart; index < mStart + mLength; index++) { 
      // Calculate average. 
      float rt = 0, gt = 0, bt = 0; 
      for (int mi = -sidePixels; mi <= sidePixels; mi++) { 
       int mindex = Math.min(Math.max(mi + index, 0), mSource.length - 1); 
       int pixel = mSource[mindex]; 
       rt += (float) ((pixel & 0x00ff0000) >> 16)/mBlurWidth; 
       gt += (float) ((pixel & 0x0000ff00) >> 8)/mBlurWidth; 
       bt += (float) ((pixel & 0x000000ff) >> 0)/mBlurWidth; 
      } 

      // Re-assemble destination pixel. 
      int dpixel = (0xff000000) 
        | (((int) rt) << 16) 
        | (((int) gt) << 8) 
        | (((int) bt) << 0); 
      mDestination[index] = dpixel; 
     } 
    } 
    protected static int sThreshold = 10000; 

    @Override 
    protected void compute() { 
     if (mLength < sThreshold) { 
      computeDirectly(); 
      return; 
     } 

     int split = mLength/2; 

     invokeAll(new ForkBlur(mSource, mStart, split, mDestination), 
       new ForkBlur(mSource, mStart + split, mLength - split, 
       mDestination)); 
    } 

    // Plumbing follows. 
    public static void main(String[] args) throws Exception { 
     String srcName = "/Users/justin/NetBeansProjects/JavaTutorialOracle/src/JTOConcurrency/Screen Shot 2015-12-28 at 10.45.31 PM.jpg"; 
     File srcFile = new File(srcName); 
     BufferedImage image = ImageIO.read(srcFile); 

     System.out.println("Source image: " + srcName); 

     BufferedImage blurredImage = blur(image); 

     String dstName = "blurred-tulips.jpg"; 
     File dstFile = new File(dstName); 
     ImageIO.write(blurredImage, "jpg", dstFile); 

     System.out.println("Output image: " + dstName); 

    } 

    public static BufferedImage blur(BufferedImage srcImage) { 
     int w = srcImage.getWidth(); 
     System.out.println("w: " + w); 
     int h = srcImage.getHeight(); 
     System.out.println("h: " + h); 

     int[] src = srcImage.getRGB(0, 0, w, h, null, 0, w); 

     System.out.println("Array size is " + src.length); 
     System.out.println("Threshold is " + sThreshold); 

     int processors = Runtime.getRuntime().availableProcessors(); 
     System.out.println(Integer.toString(processors) + " processor" 
       + (processors != 1 ? "s are " : " is ") 
       + "available"); 

     ForkBlur fb = new ForkBlur(src, 0, src.length, dst); 

     ForkJoinPool pool = new ForkJoinPool(); 

     long startTime = System.currentTimeMillis(); 
     pool.invoke(fb); 

     long endTime = System.currentTimeMillis(); 

     System.out.println("Image blur took " + (endTime - startTime) + 
       " milliseconds."); 

     BufferedImage dstImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
     dstImage.setRGB(0, 0, w, h, dst, 0, w); 

     return dstImage; 
    } 
} 

回答

2

Forkblur被延伸java.util.concurrent.RecursiveAction其包含方法compute()和把它描述爲「該任務執行的主要運算」。基本上會發生以下情況:

當你調用ForkJoinPool.invoke()並指定要執行的任務(在這種情況下,ForkBlur是一個ForkJoinTask的實現),JAVA SDK實際上啓動了多個線程,每個線程執行指示任務,採取並行方式。要執行的實際操作在compute()方法中定義。因此,這個方法總是由JAVA SDK調用,並且永遠不會被程序員調用。

+0

非常感謝你的解釋!現在一切都開始有意義了! – Thor

相關問題