并行四个任务执行

时间:2018-04-23 06:10:45

标签: java parallel-processing aes executorservice

我想独立使用四个线程并行执行四个任务。我想减少执行时间。但是这个程序不能减少执行时间。在这个程序中,顺序执行时间小于并行执行时间。我希望从顺序执行中更快地执行程序。我怎样才能使四个任务并行执行并减少执行时间。请删除此代码的问题并提供解决方案。

package TestParallel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 *
 * @author Sohel Rana
 */
public class Executor {

    public void encrypt(File fname) throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256);  //using AES-256
        SecretKey key = keyGen.generateKey();  //generating key
        //  System.out.println("Key = " + bytesToHex(key.getEncoded()));
        Cipher aesCipher = Cipher.getInstance("AES");  //getting cipher for AES
        aesCipher.init(Cipher.ENCRYPT_MODE, key);  //initializing cipher for encryption with key

        //creating file output stream to write to file
        try (FileOutputStream fos = new FileOutputStream(fname + ".aes")) {
            //creating object output stream to write objects to file
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(key);  //saving key to file for use during decryption

            //creating file input stream to read contents for encryption
            try (FileInputStream fis = new FileInputStream(fname)) {
                //creating cipher output stream to write encrypted contents
                try (CipherOutputStream cos = new CipherOutputStream(fos, aesCipher)) {
                    int read;
                    byte buf[] = new byte[4096];
                    while ((read = fis.read(buf)) != -1) //reading from file
                    {
                        cos.write(buf, 0, read);  //encrypting and writing to file
                    }
                }
            }
            //  fname.delete();
        }

    }

    public static void main(final String[] args) throws InterruptedException {
        final ExecutorService pool = Executors.newFixedThreadPool(4);

        File file1 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\33 - Overflow Menu.mp4");
        File file2 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\Java Cryptography Tutorials 1 AES Encryption and Decryption using Java.mp4");
        File file3 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\30 - Dank Meme Bro.mp4");
        File file4 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\How to change API level Android Studio.mp4");

        Executor ex = new Executor();
        long startTime = System.currentTimeMillis();
        pool.execute(() -> {
            try {
                ex.encrypt(file1);
                ex.encrypt(file2);
                 ex.encrypt(file3);
                ex.encrypt(file4);
            } catch (Exception ex1) {
                Logger.getLogger(Executor.class.getName()).log(Level.SEVERE, null, ex1);
            }
        });

        pool.shutdown();

        if (!pool.awaitTermination(1, TimeUnit.DAYS)) {
            System.err.println("Pool did not terminate.");
        }
                long endTime = System.currentTimeMillis();

        System.out.println("Paralle took time " + (endTime - startTime)
                + " milliseconds.");

    }
}

1 个答案:

答案 0 :(得分:3)

这是创建一个Runnable,一个接一个地运行单个encrypt

    pool.execute(() -> {
        try {
            ex.encrypt(file1);
            ex.encrypt(file2);
            ex.encrypt(file3);
            ex.encrypt(file4);
        } catch (Exception ex1) {
            Logger.getLogger(Executor.class.getName()).log(Level.SEVERE, null, ex1);
        }
    });

你需要做的是像

for (File f : new File[] { file1, file2, file3, file4}) {
    pool.execute(() -> {
        try {
            ex.encrypt(f);
        } catch (Exception ex1) {
            Logger.getLogger(Executor.class.getName()).log(Level.SEVERE, null, ex1);
        }
    });
}

作为旁注,您等待线程完成的方式仅仅因为胎面池的大小足以启动所有提交的任务而工作。如果您要扩展此解决方案以添加更多文件,那么这些文件可能永远不会被编码,因为执行程序将它们放在队列中但尚未启动;这意味着他们根本不会开始,因为这是shutdownExecutorService调用的影响之一。