我有一个问题。
我有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代码中启动一组线程并检索可接受的时间?
答案 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());