Cách tạo nhiều luồng cho mỗi mục yêu cầu


9

Tôi đang cố gắng xử lý mã dưới đây bằng cách sử dụng đa luồng ở cấp độ đặt hàng.

List<String> orders = Arrays.asList("order1", "order2", 
                   "order3", "order4", "order1");

Thực hiện tuần tự hiện tại:

orders.stream().forEach(order -> {
    rules.forEach(rule -> {
        finalList.add(beanMapper.getBean(rule)
                .applyRule(createTemplate.apply(getMetaData.apply(rule), command),
                           order));
    });
});

Tôi đã thử sử dụng:

orders.parallelStream().forEach(order -> {}} // code snippet.

Nhưng nó đang thay đổi thứ tự quy tắc.forEach (quy tắc -> {}} .

Ví dụ:
Đầu vào:

 List<String> orders = Arrays.asList("order1", "order2", 
                         "order3", "order4", "order1");
 List<String> rules = Arrays.asList("rule1", "rule2", "rule3");

Sản lượng dự kiến:

order1 with rule1, rule2, rule3
order2 with rule1, rule2, rule3

Sản lượng thực tế với parallelStream():

order1 with rule3, rule1, rule2
order1 with rule2, rule1, rule3

Tôi không bận tâm về thứ tự của các đơn đặt hàng , nhưng tôi bận tâm về thứ tự eh của các quy tắc . Đơn đặt hàng có thể xử lý theo bất kỳ thứ tự nào, nhưng các quy tắc sẽ thực hiện theo cùng một thứ tự cho mỗi đơn hàng.

Xin vui lòng giúp đỡ.

Câu trả lời:


4

Bạn có thể dùng :

orders.stream().parallel().forEachOrdered(// Your rules logic goes here. )

ForEachOrdered đảm bảo duy trì thứ tự của Luồng.

Vì vậy, để bạn tham khảo:

orders.stream().parallel().forEachOrdered( order -> {

            rules.stream().parallel().forEachOrdered ( rule -> {

                 System.out.println( " Order : " + order + " rule :" + rule);
            });

        });

Ghi chú : Mặc dù chúng tôi có thể làm điều này, hiệu suất nên được theo dõi chặt chẽ bởi vì sự tương đồng và trật tự không kết hôn với nhau rất tốt!

Đầu ra

 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order1 rule :rule3
 Order : order2 rule :rule1
 Order : order2 rule :rule2
 Order : order2 rule :rule3
 Order : order3 rule :rule1
 Order : order3 rule :rule2
 Order : order3 rule :rule3
 Order : order4 rule :rule1
 Order : order4 rule :rule2
 Order : order4 rule :rule3
 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order1 rule :rule3

Cảm ơn câu trả lời. forEachOrdered đảm bảo thứ tự của luồng, nhưng sau đó nó cũng làm chậm hiệu suất. Tôi đã thử nó và ứng dụng đang mất thời gian tương tự như xử lý tuần tự. stream () .allel & forEachOrdered không khen nhau.
bisht bisht

Yup tôi đồng ý chúng ta cần thực hiện phân tích độ trễ đầy đủ trước khi làm điều này.
Pramod S. Nikam

Yup, tôi đang nhận được hiệu suất tương tự bằng cách sử dụng này, không có cải thiện.
Mayank bisht

1
Theo sát chủ đề này để có giải pháp tốt hơn để làm điều này.
Pramod S. Nikam

Tôi có thể đạt được xử lý song song bằng ExecutorService không?
Mayank bisht

1

Bạn thêm các yếu tố vào finalList từ các chủ đề khác nhau cùng một lúc. Điều này gây ra kết quả trộn lẫn của việc áp dụng các quy tắc cho các đơn hàng khác nhau (quy tắc không được nhóm theo đơn đặt hàng của chúng).

Bạn có thể sửa nó bằng cách tạo một danh sách tạm thời cho mỗi danh sách ordervà sau đó hợp nhất tất cả các danh sách tạm thời trong mộtfinalList .

Đây là cách bạn có thể làm điều đó bằng Stream-API (Java 9+):

List<AppliedRule> finalList = orders.parallelStream().map(order ->
        rules.stream().map(rule -> applyRule(order, rule)).collect(Collectors.toList())
).collect(Collectors.flatMapping(Collection::stream, Collectors.toList()));

Lưu ý: Collectors.flatMapping()được sử dụng ở đây thay vì đơn giản flatMapđể chạy ánh xạ phẳng đồng bộ trong quá trình thu thập luồng.


Tương tự Java 8:

List<AppliedRule> finalList = orders.parallelStream().map(order ->
        rules.stream().map(rule -> applyRule(order, rule)).collect(Collectors.toList())
).collect(Collectors.toList())
        .stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

Cảm ơn câu trả lời. Tôi đã thử cách tiếp cận của bạn và tôi đang nhận java.util.ConcienModificationException: null
bankt bisht

FinalList = order.poolStream () .map (order -> rule.stream () .map (rule -> beanMapper.getBean (rule) .applyRule (createdTemplate.apply (getMetaData.apply (rule), lệnh), order)) .collect (Collector.toList ())). coll (Collector.toList ()). stream (). FlatMap (Collection :: stream) .collect (Collector.toList ());
mayank bisht

@mayankbisht, điều này có nghĩa là đó beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)không phải là một hàm thuần túy, vì vậy nó không thể được sử dụng song song. Cố gắng loại bỏ tất cả các tác dụng phụ từ nó; ConcurrentModificationExceptiondấu vết ngăn xếp có thể giúp xác định vị trí của họ.
Tuneon

0

Điều này sẽ làm việc?

final int rulesSize = rules.size();
AtomicInteger atomicInteger = new AtomicInteger(0);
orders.stream().parallel().forEach(order -> {
    IntStream.range(0, rulesSize).parallel().forEach( i -> {
        synchronized (atomicInteger) {
            System.out.println(" Order : " + order + " rule :" + rules.get(atomicInteger.getAndIncrement() % rulesSize));
        }
    });
});

Đầu ra

 Order : order1 rule :rule1
 Order : order4 rule :rule2
 Order : order1 rule :rule3
 Order : order3 rule :rule1
 Order : order3 rule :rule2
 Order : order3 rule :rule3
 Order : order2 rule :rule1
 Order : order2 rule :rule2
 Order : order2 rule :rule3
 Order : order1 rule :rule1
 Order : order1 rule :rule2
 Order : order4 rule :rule3
 Order : order1 rule :rule1
 Order : order4 rule :rule2
 Order : order1 rule :rule3

0

Thứ tự của các đơn đặt hàng có thể là bất cứ điều gì, nhưng thứ tự của các quy tắc không nên thay đổi. Ngoài ra đối với một quy tắc đặt hàng cụ thể nên đi trong một nhóm.

Nếu đó là trường hợp, không có chỗ cho sự song song thực tế.

Khi nào

order1-rule1
order1-rule2
order2-rule1
order2-rule2

order2-rule1
order2-rule2
order1-rule1
order1-rule2

là các lần chạy hợp lệ duy nhất cho 2 đơn đặt hàng và 2 quy tắc

order1-rule1
order2-rule1
order1-rule2
order2-rule2

được coi là không hợp lệ, đó không phải là song song, chỉ là ngẫu nhiên của orders, có lẽ không có lợi. Nếu bạn "chán" với việc order1đến trước mọi lúc, bạn có thể xáo trộn danh sách, nhưng đó là tất cả:

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    Collections.shuffle(orders);
    orders.forEach(order->{
        rules.forEach(rule->{
            System.out.println(order+"-"+rule);
        });
    });
}

Thậm chí không cần phát trực tuyến, chỉ cần hai vòng lặp lồng nhau. Kiểm tra: https://ideone.com/qI3dqd

order2-rule1
order2-rule2
order2-rule3
order4-rule1
order4-rule2
order4-rule3
order1-rule1
order1-rule2
order1-rule3
order3-rule1
order3-rule2
order3-rule3


Câu trả lời gốc

Nhưng nó đang thay đổi thứ tự quy tắc.forEach (quy tắc -> {}}.

Không nó không. Cácorder s có thể trùng nhau, nhưng thứ tự của rules cho mỗi đơn hàng được giữ. Tại sao một người không song song forEachlàm bất cứ điều gì khác?

Mã ví dụ:

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    orders.stream().parallel().forEach(order->{
        rules.forEach(rule->{
            System.out.println(order+"-"+rule);
        });
    });
}

Kiểm tra: https://ideone.com/95Cybg
Ví dụ đầu ra:

order2-rule1
order2-rule2
order2-rule3
order1-rule1
order1-rule2
order1-rule3
order4-rule1
order4-rule2
order4-rule3
order3-rule1
order3-rule2
order3-rule3

Lệnh của order s là hỗn hợp, nhưng rules luôn là 1-2-3. Tôi nghĩ rằng đầu ra của bạn chỉ đơn giản là ẩn các cặp (thực ra bạn không cho thấy nó được tạo như thế nào).

Tất nhiên nó có thể được gia hạn với một số độ trễ, vì vậy xử lý order s sẽ thực sự trùng lặp:

public static void delay(){
    try{
        Thread.sleep(ThreadLocalRandom.current().nextInt(100,300));
    }catch(Exception ex){}
}

public static void main (String[] args) throws java.lang.Exception
{
    List<String> orders = Arrays.asList("order1", "order2", "order3", "order4");
    List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
    orders.stream().parallel().forEach(order->{
        rules.forEach(rule->{
            delay();
            System.out.println(order+"-"+rule);
        });
    });
}

Kiểm tra: https://ideone.com/cSFaqS Kết
quả đầu ra:

order3-rule1
order2-rule1
order2-rule2
order3-rule2
order3-rule3
order2-rule3
order1-rule1
order4-rule1
order1-rule2
order4-rule2
order4-rule3
order1-rule3

Đây có thể là một cái gì đó bạn đã thấy, chỉ cần không có orderxphần. Với orders có thể nhìn thấy, nó có thể được theo dõi mà ruletiếp tục là 1-2-3, mỗiorder . Ngoài ra, danh sách ví dụ của bạn chứa order1hai lần mà chắc chắn không giúp ích gì trong việc nhìn thấy những gì đang xảy ra.


Cảm ơn câu trả lời. Đầu ra trên có thể đúng với số lượng đơn đặt hàng ít hơn. Nhưng nếu bạn tăng đơn hàng, thì bạn sẽ nhận được một đầu ra khác. Ví dụ:
bankt bisht

Thứ tự của các đơn đặt hàng có thể là bất cứ điều gì, nhưng thứ tự của các quy tắc không nên thay đổi. Ngoài ra đối với một quy tắc đặt hàng cụ thể nên đi trong một nhóm. Dành cho người cũ (quy tắc order1- 1 order1-rule2 order1-rule3) và không (order1-rule1 order2-rule1 order1-rule2 order1-rule3)).
Mayank bisht

@mayankbisht Tôi nghĩ rằng những hạn chế này đơn giản là không cho phép xử lý song song. Xem câu trả lời cập nhật (tôi đã viết phần mới ở đầu).
tevemadar

Vâng, tôi hiểu điều đó, và đó là lý do tại sao tôi đăng câu hỏi này ở đây. Tôi nghĩ có lẽ sẽ có cách khác để làm điều này, hoặc có thể chúng ta có thể thay đổi thuật toán
mayank bisht

@mayankbisht bạn có thể mô tả lý do tại sao orders không thể trùng nhau ( rulecó lẽ chúng có trạng thái và tồn tại trong một số lượng hạn chế, có lẽ chỉ là một bản sao?). Nhưng nhìn chung không có sự song song mà không có những thứ chạy song song, đó là toàn bộ điểm của sự song song.
tevemadar

0

Nếu bạn không thử dùng thư viện của bên thứ ba. Đây là mẫu với thư viện của tôi: bàn tính

StreamEx.of(orders).parallelStream().forEach(order -> {}}

Và bạn thậm chí có thể chỉ định số chủ đề:

StreamEx.of(orders).parallelStream(maxThreadNum).forEach(order -> {}}

Thứ tự rulesẽ được giữ.

Nhân tiện, vì nó nằm trong luồng song song, nên đoạn mã ...finalList.add(...rất có thể sẽ không hoạt động. Tôi nghĩ tốt hơn là thu thập kết quả vào danh sách:

StreamEx.of(orders).parallelStream().map/flatMap(order -> {...}}.toList()

nó cũng có thể thực hiện được ngay cả khi bạn muốn giữ trật tự ordervì một số lý do sau:

StreamEx.of(orders).indexed().parallelStream()
      .map/flatMap(order -> {...}}.sortedBy(...index).toList()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.