AtomicInteger recordNumber = new AtomicInteger();
Files.lines(inputFile.toPath(), StandardCharsets.UTF_8)
.map(record -> new Record(recordNumber.incrementAndGet(), record))
.parallel()
.filter(record -> doSomeOperation())
.findFirst()
Khi tôi viết điều này, tôi giả sử rằng các luồng sẽ chỉ xuất hiện cuộc gọi bản đồ vì song song được đặt sau bản đồ. Nhưng một số dòng trong tệp đã nhận được số lượng bản ghi khác nhau cho mỗi lần thực hiện.
Tôi đọc tài liệu luồng Java chính thức và một vài trang web để hiểu cách các luồng hoạt động dưới mui xe.
Một số câu hỏi:
Luồng song song Java hoạt động dựa trên SplitIterator , được triển khai bởi mọi bộ sưu tập như ArrayList, LinkedList, v.v. Điều này giải thích tại sao sự song song xảy ra ở cấp nguồn đầu vào ban đầu (Dòng tệp) thay vì kết quả của bản đồ (tức là Record pojo). Tôi hiểu có đúng không?
Trong trường hợp của tôi, đầu vào là một luồng IO tệp. Lặp lại phân chia sẽ được sử dụng?
Nó không quan trọng nơi chúng tôi đặt
parallel()
trong đường ống. Nguồn đầu vào ban đầu sẽ luôn được phân chia và các hoạt động trung gian còn lại sẽ được áp dụng.Trong trường hợp này, Java không nên cho phép người dùng đặt hoạt động song song ở bất kỳ đâu trong đường ống ngoại trừ tại nguồn ban đầu. Bởi vì, nó mang lại hiểu sai cho những người không biết cách java hoạt động nội bộ. Tôi biết
parallel()
hoạt động sẽ được xác định cho loại đối tượng Stream và vì vậy, nó đang hoạt động theo cách này. Nhưng, tốt hơn là cung cấp một số giải pháp thay thế.Trong đoạn mã trên, tôi đang cố gắng thêm một số dòng vào mỗi bản ghi trong tệp đầu vào và do đó nó phải được đặt hàng. Tuy nhiên, tôi muốn áp dụng
doSomeOperation()
song song vì nó là logic nặng. Một cách để đạt được là viết trình lặp phân tách tùy chỉnh của riêng tôi. Còn cách nào khác không?
Stream
trực tiếp trong giao diện và do xếp tầng đẹp nên mọi thao tác sẽ quay trở Stream
lại. Hãy tưởng tượng ai đó muốn cung cấp cho bạn Stream
nhưng đã áp dụng một vài thao tác như thế map
. Bạn, với tư cách là người dùng, vẫn muốn có thể quyết định có thực hiện song song hay không. Vì vậy, bạn phải có thể gọi parallel()
tĩnh, mặc dù luồng đã tồn tại.
flatMap
hoặc nếu bạn thực thi các phương thức không an toàn của luồng hoặc tương tự.
Path
có trên hệ thống tệp cục bộ và bạn đang sử dụng JDK gần đây, trình phân tách sẽ có khả năng xử lý song song tốt hơn so với các bội số của 1024. Nhưng việc chia tách cân bằng thậm chí có thể phản tác dụng trong một số findFirst
trường hợp
parallel()
không gì khác hơn là một yêu cầu sửa đổi chung được áp dụng cho đối tượng luồng bên dưới. Hãy nhớ rằng chỉ có một luồng nguồn nếu bạn không áp dụng các thao tác cuối cùng cho đường ống, tức là miễn là không có gì được "thực thi". Phải nói rằng, về cơ bản, bạn chỉ đang đặt câu hỏi về các lựa chọn thiết kế Java. Đó là ý kiến dựa trên và chúng tôi thực sự không thể giúp với điều đó.