Автор оригинала: mkyong.
Несколько примеров Java 8 для параллельного выполнения потоков.
1. Базовый поток.параллельный()
Простой параллельный пример для печати от 1 до 10.
package com.mkyong.java8;
import java.util.stream.IntStream;
public class ParallelExample1 {
public static void main(String[] args) {
System.out.println("Normal...");
IntStream range = IntStream.rangeClosed(1, 10);
range.forEach(System.out::println);
System.out.println("Parallel...");
IntStream range2 = IntStream.rangeClosed(1, 10);
range2.parallel().forEach(System.out::println);
}
}
Выход
Normal... 1 2 3 4 5 6 7 8 9 10 Parallel... 7 6 8 9 10 1 4 5 3 2
2. Коллекция.Параллельный поток()
Еще один простой параллельный пример для печати a в z . Для сбора данных мы можем использовать parallelStream() .
package com.mkyong.java8;
import java.util.ArrayList;
import java.util.List;
public class ParallelExample2 {
public static void main(String[] args) {
System.out.println("Normal...");
List alpha = getData();
alpha.stream().forEach(System.out::println);
System.out.println("Parallel...");
List alpha2 = getData();
alpha2.parallelStream().forEach(System.out::println);
}
private static List getData() {
List alpha = new ArrayList<>();
int n = 97; // 97 = a , 122 = z
while (n <= 122) {
char c = (char) n;
alpha.add(String.valueOf(c));
n++;
}
return alpha;
}
}
Выход
Normal... a b c d e f g h i j k l m n o p q r s t u v w x y z Parallel... q s r o x h l p d i g t u n z v j k w f m c a e b y
3. Работает ли поток в параллельном режиме?
3.1 Мы можем проверить это с помощью параллельно()
package com.mkyong.java8;
import java.util.stream.IntStream;
public class ParallelExample3a {
public static void main(String[] args) {
System.out.println("Normal...");
IntStream range = IntStream.rangeClosed(1, 10);
System.out.println(range.isParallel()); // false
range.forEach(System.out::println);
System.out.println("Parallel...");
IntStream range2 = IntStream.rangeClosed(1, 10);
IntStream range2Parallel = range2.parallel();
System.out.println(range2Parallel.isParallel()); // true
range2Parallel.forEach(System.out::println);
}
}
3.2 Или выведите текущее имя потока следующим образом:
package com.mkyong.java8;
import java.util.stream.IntStream;
public class ParallelExample3b {
public static void main(String[] args) {
System.out.println("Normal...");
IntStream range = IntStream.rangeClosed(1, 10);
range.forEach(x -> {
System.out.println("Thread : " + Thread.currentThread().getName() + ", value: " + x);
});
System.out.println("Parallel...");
IntStream range2 = IntStream.rangeClosed(1, 10);
range2.parallel().forEach(x -> {
System.out.println("Thread : " + Thread.currentThread().getName() + ", value: " + x);
});
}
}
Выход
Normal... Thread : main, value: 1 Thread : main, value: 2 Thread : main, value: 3 Thread : main, value: 4 Thread : main, value: 5 Thread : main, value: 6 Thread : main, value: 7 Thread : main, value: 8 Thread : main, value: 9 Thread : main, value: 10 Parallel... Thread : main, value: 7 Thread : main, value: 6 Thread : ForkJoinPool.commonPool-worker-5, value: 3 Thread : ForkJoinPool.commonPool-worker-7, value: 8 Thread : ForkJoinPool.commonPool-worker-5, value: 5 Thread : ForkJoinPool.commonPool-worker-5, value: 4 Thread : ForkJoinPool.commonPool-worker-3, value: 9 Thread : ForkJoinPool.commonPool-worker-5, value: 1 Thread : ForkJoinPool.commonPool-worker-7, value: 2 Thread : ForkJoinPool.commonPool-worker-9, value: 10
P.S По умолчанию параллельные потоки используют “ForkJoinPool`
4. Расчет
4.1 Потоки Java 8 для печати всех простых чисел до 1 миллиона:
package com.mkyong.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class ParallelExample4 {
public static void main(String[] args) {
long count = Stream.iterate(0, n -> n + 1)
.limit(1_000_000)
//.parallel() with this 23s, without this 1m 10s
.filter(ParallelExample4::isPrime)
.peek(x -> System.out.format("%s\t", x))
.count();
System.out.println("\nTotal: " + count);
}
public static boolean isPrime(int number) {
if (number <= 1) return false;
return !IntStream.rangeClosed(2, number / 2).anyMatch(i -> number % i == 0);
}
}
Результат:
- Для обычных потоков это занимает 1 минуту 10 секунд.
- Для параллельных потоков это занимает 23 секунды.
P.S Протестирован с i7-7700, 16 ГБ оперативной памяти, Windows 10
4.2 Еще один пример параллельного потока для определения среднего возраста списка сотрудников.
Listemployees = obj.generateEmployee(10000); double age = employees .parallelStream() .mapToInt(Employee::getAge) .average() .getAsDouble(); System.out.println("Average age: " + age);
5. тематическое исследование
5.1 Параллельные потоки для повышения производительности трудоемких задач сохранения файлов.
Этот Java-код сгенерирует 10 000 случайных сотрудников и сохранит в 10 000 файлов, каждый сотрудник сохранит в файл.
- Для обычного потока это занимает 27-29 секунд.
- Для параллельного потока это занимает 7-8 секунд.
P.S Протестирован с i7-7700, 16 ГБ оперативной памяти, Windows 10
package com.mkyong.java8;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ParallelExample5 {
private static final String DIR = System.getProperty("user.dir") + "/test/";
public static void main(String[] args) throws IOException {
Files.createDirectories(Paths.get(DIR));
ParallelExample5 obj = new ParallelExample5();
List employees = obj.generateEmployee(10000);
// normal, sequential
//employees.stream().forEach(ParallelExample5::save); // 27s-29s
// parallel
employees.parallelStream().forEach(ParallelExample5::save); // 7s-8s
}
private static void save(Employee input) {
try (FileOutputStream fos = new FileOutputStream(new File(DIR + input.getName() + ".txt"));
ObjectOutputStream obs = new ObjectOutputStream(fos)) {
obs.writeObject(input);
} catch (IOException e) {
e.printStackTrace();
}
}
private List generateEmployee(int num) {
return Stream.iterate(0, n -> n + 1)
.limit(num)
.map(x -> {
return new Employee(
generateRandomName(4),
generateRandomAge(15, 100),
generateRandomSalary(900.00, 200_000.00)
);
})
.collect(Collectors.toList());
}
private String generateRandomName(int length) {
return new Random()
.ints(5, 97, 122) // 97 = a , 122 = z
.mapToObj(x -> String.valueOf((char) x))
.collect(Collectors.joining());
}
private int generateRandomAge(int min, int max) {
return new Random()
.ints(1, min, max)
.findFirst()
.getAsInt();
}
private BigDecimal generateRandomSalary(double min, double max) {
return new BigDecimal(new Random()
.doubles(1, min, max)
.findFirst()
.getAsDouble()).setScale(2, RoundingMode.HALF_UP);
}
}
package com.mkyong.java8;
import java.io.Serializable;
import java.math.BigDecimal;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private BigDecimal salary;
//getters, setters n etc...
}
- Учебные пособия по Java – Параллелизм
- Поток Java 8.повторяйте примеры
- Примеры простых чисел Java
- Что не так в Java 8, Часть III: Потоки и Параллельные потоки
Оригинал: “https://mkyong.com/java8/java-8-parallel-streams-examples/”