多线程示例:图像处理中的数据分解

时间:2015-12-01 14:50:43

标签: java multithreading parallel-processing decomposition

目前我正在编写一个使用基本多线程的java程序的示例。我想在类似于单色滤波器的图像处理应用中展示数据合成原理的优点。我在缓冲区中加载一张图片然后生成四个线程,这些线程都计算图像的不同部分。

图像分为四个切片,根据我的预期,单独的计算时间会降低(在四核上快3到4倍)。 问题是我试图通过给每个线程一个缓冲区来保护计算图像来避免竞争条件。在执行之后,每个线程将它的部分图片保存在jpg中。

我的问题是,如果有一种模式可以用来将不同的切片再次保存为一张图片,同时避免共享可变状态变量的危险。 如果我在我的处理类中使用静态变量来重新组合图片,那么我得到的时间甚至比单线程解决方案更糟糕。 如何在这个例子中提高多线程提供的效率?

多线程应用程序的代码:

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;


public class Main {
  static int threadCount=4;
  public static void main(String[] args) {
    // TODO Auto-generated method stub
      BufferedImage original=null;
      BufferedImage greyscale=null;

      //loading Picture into Buffer
    try{
           original = ImageIO.read(new File("Desert.jpg"));
         }
    catch (IOException e) 
    {
            e.printStackTrace();

    }


        ArrayList<Thread> threads = new ArrayList<Thread>();


        //Creating Threads, each Thread gets a Copy of the Image
        for( int i=0; i < threadCount; i++)

        {
            final int threadNumber =i;

            threads.add(new Thread(new Processor2(deepCopy(original),threadNumber,threadCount)));}

        //threads gets started
        long start = System.currentTimeMillis();
        for( int i=0; i < threadCount; i++){
            threads.get(i).start();
        }

        for( int i=0; i < threadCount; i++){
            try {
                threads.get(i).join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        long end = System.currentTimeMillis();


        long seconds = (end-start);
         System.out.println("Dauer: "+seconds+" ms.");

}

//Method that copies the Image
static BufferedImage deepCopy(BufferedImage bi) {
 ColorModel cm = bi.getColorModel();
 boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
 WritableRaster raster = bi.copyData(null);
 return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
 }


}

产生的线程执行此代码:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Processor2 implements Runnable  {




 BufferedImage greyscale;
 BufferedImage original;

int threadNumber, threadCount;

//The Constructor gets the Image, the total number of Threads and the own Threadnumber.
Processor2(BufferedImage image, int x, int y){
    this.original=image;

    threadNumber=x;
    threadCount=y;
}
Object lock =new Object();
@Override

// The run Method goes through the pixel of the assignes slide of the picture, renders it monochromatic and then saves it in an ImageBuffer. This image is saved after the loop has reached all pixels.
public void run() {
    // TODO Auto-generated method stub
int part =original.getWidth()/threadCount;
    greyscale = new BufferedImage(part,     original.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
    int x=0;
    try{for(int i=threadNumber*part; i<part*(threadNumber+1); i++) 
    {
        for(int j=0; j<original.getHeight(); j++)
        {

            // Get pixels
            int rgb = original.getRGB(i, j);
            int a = (rgb>>24)&0xff;
            int r = (rgb >> 16) & 0xFF;
            int g = (rgb >> 8) & 0xFF;
            int b = (rgb & 0xFF);

            int avg = (r + g + b) / 3;
            int gray = colorToRGB(a, avg, avg, avg);
            greyscale.setRGB(x, j, gray);

           } x++;
}}
    finally{
    saveImage(greyscale, threadNumber);
        }
}


public void start(){

}

private static int colorToRGB(int alpha, int red, int green, int blue) {
    int newPixel = 0;
    newPixel += alpha;
    newPixel = newPixel << 8;
    newPixel += red; newPixel = newPixel << 8;
    newPixel += green; newPixel = newPixel << 8;
    newPixel += blue;

    return newPixel;
}

static void saveImage(BufferedImage r,int threadNumber){

    try {
        ImageIO.write(r, "png",new    File("blackwhiteimageshared"+threadNumber+".png") );
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
  }

 }

此代码比在一个线程中循环中的每个像素快两到三倍。 生产者消费者模式是否是将代码更改为一种状态的好方法,即在执行后我在合理的时间内有一个单色图像而不是4个部分?

0 个答案:

没有答案