AtomicInteger recordNumber = new AtomicInteger();
Files.lines(inputFile.toPath(), StandardCharsets.UTF_8)
.map(record -> new Record(recordNumber.incrementAndGet(), record))
.parallel()
.filter(record -> doSomeOperation())
.findFirst()
Ketika saya menulis ini, saya berasumsi bahwa utas akan memunculkan hanya panggilan peta karena paralel ditempatkan setelah peta. Tetapi beberapa baris dalam file mendapatkan nomor catatan yang berbeda untuk setiap eksekusi.
Saya membaca dokumentasi stream Java resmi dan beberapa situs web untuk memahami bagaimana stream bekerja di bawah tenda.
Beberapa pertanyaan:
Java parallel stream bekerja berdasarkan SplitIterator , yang diimplementasikan oleh setiap koleksi seperti ArrayList, LinkedList dll. Ketika kita membangun aliran paralel dari koleksi-koleksi itu, iterator split yang sesuai akan digunakan untuk membagi dan mengulangi koleksi. Ini menjelaskan mengapa paralelisme terjadi pada tingkat sumber input asli (File lines) bukan pada hasil peta (yaitu Rekam pojo). Apakah pemahaman saya benar?
Dalam kasus saya, inputnya adalah aliran file IO. Iterator split mana yang akan digunakan?
Tidak masalah di mana kita menempatkan
parallel()
pipa. Sumber input asli akan selalu dipecah dan operasi perantara yang tersisa akan diterapkan.Dalam hal ini, Java seharusnya tidak mengizinkan pengguna untuk menempatkan operasi paralel di mana saja dalam pipa kecuali pada sumber aslinya. Karena, ini memberikan pemahaman yang salah bagi mereka yang tidak tahu bagaimana java stream bekerja secara internal. Saya tahu
parallel()
operasi akan ditentukan untuk tipe objek Stream dan karenanya, ia bekerja dengan cara ini. Tetapi, lebih baik memberikan beberapa solusi alternatif.Dalam cuplikan kode di atas, saya mencoba menambahkan nomor baris ke setiap catatan dalam file input dan karenanya harus dipesan. Namun, saya ingin menerapkannya
doSomeOperation()
secara paralel karena ini adalah logika yang berat. Satu-satunya cara untuk mencapai adalah menulis iterator split saya sendiri. Apakah ada cara lain?
Stream
antarmuka secara langsung dan karena cascading yang bagus setiap operasi memberikan kembali Stream
lagi. Bayangkan seseorang ingin memberi Anda Stream
tetapi sudah menerapkan beberapa operasi seperti map
itu. Anda, sebagai pengguna, masih ingin dapat memutuskan apakah akan menjalankannya secara paralel atau tidak. Jadi Anda harus parallel()
tetap menelepon , meskipun streaming sudah ada.
flatMap
atau jika Anda menjalankan metode thread-tidak aman atau serupa.
Path
ada pada sistem file lokal dan Anda menggunakan JDK baru-baru ini, spliterator akan memiliki kemampuan pemrosesan paralel yang lebih baik daripada kumpulan batch 1024. Tetapi pemisahan yang seimbang mungkin bahkan kontraproduktif dalam beberapa findFirst
skenario ...
parallel()
tidak lebih dari permintaan pengubah umum yang diterapkan ke objek aliran yang mendasarinya. Ingat bahwa hanya ada satu sumber-aliran jika Anda tidak menerapkan operasi akhir ke pipa, yaitu selama tidak ada yang "dieksekusi". Karena itu, Anda pada dasarnya hanya mempertanyakan pilihan desain Java. Yang berdasarkan opini dan kami tidak bisa membantu dengan itu.