我如何在Java代码中启动一组Thread

时间:2014-09-30 12:31:27

标签: java multithreading

我有一个问题。

我有10000个字符串,我想对每个字符串执行一些操作。我想并行化这些操作,以使总执行时间可以接受。

我决定创建线程。特别是,我每10个字符串启动10个线程。对于每个线程,我将结果保存在列表中。

我已经尝试了两个版本的代码。这是我的第一个版本。

int size = 10000;
int cont = 0;
        int n = 1;
        String[] arrstr2;
        int threadgroup = 10;
if (cont + threadgroup - 1 > size) {
                        arrstr2[i - cont] = subject.toString();
                    } else {
                        arrstr2[i - cont] = subject.toString();
                    }

                    if ((i == (threadgroup * n) - 1) || (i == size - 1)) {

                        cont = i + 1;
                        n = n + 1;
                        for (int j = 0; j < arrstr2.length; j++) {
                            Thread t = new Thread(new MyThread(arrstr2[j], l));
                            t.start();

                            try {
                                t.join();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        if (cont + threadgroup - 1 > size) {
                            arrstr2 = new String[size - i - 1];
                        }
                    }
                    i = i + 1;

在这个版本中,我不会在总执行中获得优势。

这是我的第二个版本:

    int size = 10000;
    int cont = 0;
            int n = 1;
            String[] arrstr2;
            int threadgroup = 10;
    if (cont + threadgroup - 1 > size) {
                            arrstr2[i - cont] = subject.toString();
                        } else {
                            arrstr2[i - cont] = subject.toString();
                        }

                        if ((i == (threadgroup * n) - 1) || (i == size - 1)) {

                            cont = i + 1;
                            n = n + 1;
                            for (int j = 0; j < arrstr2.length; j++) {
                                Thread t = new Thread(new MyThread(arrstr2[j], l));
                                t.start();

                            }
try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            if (cont + threadgroup - 1 > size) {
                                arrstr2 = new String[size - i - 1];
                            }
                        }
                        i = i + 1;

在这种情况下,我丢失了一些信息。 MyThread是一个进行一些处理并将结果放在列表java中的类:

public class MyThread implements Runnable{

    String subject;
    private List<String[]> l;

    public MyThread(String subject, List<String[]> l) {
        this.subject = subject;
        this.l = l;
    }

    @Override
    public void run() {

        synchronized (l){
        //do something
        String[] result = new String[2];
        result[0] = res0;
        result[1] = res1;
        l.add(result);
    }
}

为了我的目标,这段代码是正确的?如何在Java代码中启动一组线程并检索可接受的时间?

3 个答案:

答案 0 :(得分:1)

也许您可以查看新的Java 8 Stream API。 http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html 在那里,您可以轻松地并行化这些操作。

答案 1 :(得分:1)

这是一个ExecutorService的小例子。螺纹尺寸固定为10,但您可以根据需要进行调整。

StringTask基本上会反转给定的字符串。

public class Test {

    private static final int THREADS = 10;
    private static final int DATA_SIZE = 1000;

    public static void main(String[] args) {
        // Declare a new ExecutorService with a maximum of 2 threads.
        ExecutorService service = Executors.newFixedThreadPool(THREADS);

        // Prepare a list of Future results.
        List<Future<String>> futures = new ArrayList<Future<String>>(DATA_SIZE);

        // Submit the tasks and store the results.
        for (int i = 0; i < DATA_SIZE; i++) {
            futures.add(service.submit(new StringTask("Sample String " + i)));
        }

        // Accept no new tasks.
        service.shutdown();

        // Retrieve the actual String results.
        List<String> results = new ArrayList<String>(DATA_SIZE);
        try {
            for (Future<String> future : futures) {
                // The get() method blocks if the execution of the task is not finished.
                results.add(future.get());
                System.out.println(future.get());
            }
        } catch (ExecutionException ee) {
            System.out.println("Error while getting result!");
            ee.printStackTrace();
        } catch (InterruptedException ie) {
            System.out.println("Error while getting result!");
            ie.printStackTrace();
        }
    }

    /**
     * Callable task that reverses a given String.
     */
    private static final class StringTask implements Callable<String> {
        private String input;

        private StringTask(String input) {
            super();

            if (input == null) {
                throw new NullPointerException();
            }

            this.input = input;
        }

        @Override
        public String call() throws Exception {
            StringBuilder builder = new StringBuilder();

            for (int i = this.input.length() - 1; i >= 0; i--) {
                builder.append(this.input.charAt(i));
            }

            return builder.toString();
        }
    }
}

我在这里使用Callable而不是Runnable,因为Callable允许任务实际返回我们可以使用的结果(通过Future接口)。如果您只需要执行任务,则只需使用Runnable

即可

答案 2 :(得分:0)

使用Java 8:

List<String> res = Arrays.toStream(arrstr2)
                         .parallel()
                         .map(s -> doWork(s))
                         .collect(Collectors.toList());