线程池优化for循环
列子
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
/**
* 循环里面使用线程池执行里面东西
*/
public class Test1 {
public static ThreadPoolExecutor threadPoolExecutor;
public static List<String> list1;
public static void main(String[] args) {
//创建线程池 普通的
threadPoolExecutor = new ThreadPoolExecutor(128, 128, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(Integer.MAX_VALUE));
List<String> list = new ArrayList<>();
list.add("0");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
list.add("8");
list.add("9");
long l = System.currentTimeMillis();
m1(list);
long l1 = System.currentTimeMillis();
System.out.println("耗时:" + (l1- l) + "ms");
System.out.println(list1);
}
//没使用线程池处理
public static void m1(List<String> list) {
List<String> objects = new ArrayList<>();
list.stream().forEach(item -> {
try {
new Thread().sleep(1000);//模拟执行延迟
System.out.println("[0]" + Thread.currentThread().getName()+"----"+item);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
objects.add(item + "A");//stream内部访问不了list1
System.out.println(objects);
});
list1 = objects;
System.out.println("stream");
}
//线程没有顺序执行的,时间短
public static void m2(List<String> list) {
for (String s : list) {
// System.out.println(s);
Runnable run = new Runnable() {
public void run() {
try {
new Thread().sleep(1000);
//模拟耗时操作
System.out.println("[1]" + Thread.currentThread().getName()+"----"+s);
list1.add(s + "A");
} catch (Exception e) {
}
}
};
threadPoolExecutor.execute(run);
}
}
public static void m3(List<String> list) {
List<String> objects = new ArrayList<>();
list.stream().map(item -> {
return threadPoolExecutor.submit(() -> {
try {
new Thread().sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("[1]" + Thread.currentThread().getName()+"----"+item);
synchronized (objects) {
objects.add(item + "A");
}
});
}).forEach(future -> wait4Done(future));
list1 = objects;
}
//等待执行完成,第一个线程执行完后,才会执行下一个线程任务
public static void wait4Done(Future future) {
try {
if (future != null) {
future.get();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
效果
- m1方法:正常循环执行
[0]main----0
[0A]
[0]main----1
[0A, 1A]
[0]main----2
[0A, 1A, 2A]
[0]main----3
[0A, 1A, 2A, 3A]
[0]main----4
[0A, 1A, 2A, 3A, 4A]
[0]main----5
[0A, 1A, 2A, 3A, 4A, 5A]
[0]main----6
[0A, 1A, 2A, 3A, 4A, 5A, 6A]
[0]main----7
[0A, 1A, 2A, 3A, 4A, 5A, 6A, 7A]
[0]main----8
[0A, 1A, 2A, 3A, 4A, 5A, 6A, 7A, 8A]
[0]main----9
[0A, 1A, 2A, 3A, 4A, 5A, 6A, 7A, 8A, 9A]
stream
耗时:10188ms
[0A, 1A, 2A, 3A, 4A, 5A, 6A, 7A, 8A, 9A]
- m2方法: 使用线程池执行里循环内容
耗时:4ms
list1:null
[1]pool-1-thread-7----6
[1]pool-1-thread-4----3
[1]pool-1-thread-2----1
[1]pool-1-thread-9----8
[1]pool-1-thread-6----5
[1]pool-1-thread-3----2
[1]pool-1-thread-1----0
[1]pool-1-thread-8----7
[1]pool-1-thread-10----9
[1]pool-1-thread-5----4
- m3方法:如果不加wait4Done效果个m2一样
[1]pool-1-thread-1----0
[1]pool-1-thread-2----1
[1]pool-1-thread-3----2
[1]pool-1-thread-4----3
[1]pool-1-thread-5----4
[1]pool-1-thread-6----5
[1]pool-1-thread-7----6
[1]pool-1-thread-8----7
[1]pool-1-thread-9----8
[1]pool-1-thread-10----9
耗时:10183ms
list1:[0A, 1A, 2A, 3A, 4A, 5A, 6A, 7A, 8A, 9A]
注意
- 使用java stream时,内部不可以访问外部静态变量
- 用stream().parallel().forEach(),这个parallel是可以让循环并行的,提高了程序的效率。但是在我使用它往一个list中设置值的时候,发现了问题。由于是多线程异步运行,所以循环可能并不保证全部运行完才进行下一步,所以如果在循环之后对list有其他操作,可能这个list并不完整,这样得到的数据就会有问题。
所以正确的做法是,如果循环后面没有操作,只是需要在循环体内进行操作的话,用parallel可以提高效率。但是如果循环后面要对循环里面设置的值做操作,就不能使用parallel了。
网友评论