Pertanyaan Java, di mana thread aliran sekuensial dieksekusi?


Saat membaca dokumentasi tentang aliran, saya menemukan kalimat berikut:

  • ... mencoba mengakses status yang dapat berubah dari parameter perilaku memberi Anda pilihan yang buruk ... jika Anda tidak menyinkronkan akses ke status itu, Anda memiliki perlombaan data dan karena itu kode Anda rusak ... [1]

  • Jika parameter perilaku memang memiliki efek samping ... [tidak ada] jaminan bahwa operasi yang berbeda pada elemen "sama" dalam pipa aliran yang sama dijalankan di thread yang sama. [2]

  • Untuk setiap elemen yang diberikan, aksi dapat dilakukan kapan saja dan di thread mana pun perpustakaan memilih. [3]

Kalimat-kalimat ini tidak membuat perbedaan antara aliran sekuensial dan paralel. Jadi pertanyaan saya adalah:

  1. Di mana thread adalah pipa aliran sequential yang dieksekusi? Apakah selalu thread panggilan atau implementasi gratis untuk memilih untaian apa saja?
  2. Di mana thread adalah parameter tindakan dari operasi terminal forEach dijalankan jika aliran berurutan?
  3. Apakah saya harus menggunakan sinkronisasi apa pun saat menggunakan aliran sekuensial?


8
2017-08-24 22:03


asal


Jawaban:


  1. Stream operasi terminal memblokir operasi. Dalam hal tidak ada excution paralel, thread yang mengeksekusi operasi terminal menjalankan semua operasi dalam saluran pipa.

Definisi 1.1.  Pipeline adalah beberapa metode dirantai.

Definisi 1,2.  Intermidiasikan operasi akan ditempatkan di mana saja di aliran berharap di akhir. Mereka mengembalikan objek streaming dan tidak mengecualikan operasi apa pun di dalam pipa.

Definisi 1.3.  Operasi terminal hanya akan berada di ujung streaming. Mereka mengecualikan pipa. Mereka tidak mengembalikan objek aliran jadi tidak ada yang lain Intermidiasikan operasi atau operasi terminal dapat ditambahkan setelah mereka.

  1. Dari solusi pertama kita dapat menyimpulkan bahwa benang panggilan akan mengeksekusi action metode di dalam forEach  operasi terminal pada setiap elemen di aliran panggilan.

Java 8 memperkenalkan kami Spliterator antarmuka. Ia memiliki kemampuan Iterator tetapi juga serangkaian operasi untuk membantu melakukan dan membagi tugas secara paralel.

Saat menelepon forEach dari aliran primitif dalam eksekusi berurutan, utas panggilan akan memanggil Spliterator.forEachRemaining metode:

@Override
public void forEach(IntConsumer action) {
   if (!isParallel()) {
        adapt(sourceStageSpliterator()).forEachRemaining(action);
    }
    else {
        super.forEach(action);
    }
}

Anda dapat membaca lebih lanjut Spliterator di tutorial saya: Bab 7: Spliterator

  1. Selama Anda tidak memutasikan status bersama apa pun antara beberapa untaian dalam salah satu operasi aliran (dan itu dilarang - dijelaskan segera), Anda tidak perlu menggunakan alat atau algoritma sinkronisasi tambahan ketika Anda ingin menjalankan aliran paralel.

Aliran operasi seperti mengurangi penggunaan accumulator dan combiner fungsi untuk menjalankan aliran paralel. Perpustakaan sungai dengan definisi melarang mutasi. Anda harus menghindarinya.

Ada banyak definisi dalam pemrograman bersamaan dan paralel. Saya akan memperkenalkan satu set definisi yang akan memberi kita yang terbaik.

Definisi 8.1.  Pemrograman Cuncurrent adalah kemampuan untuk menyelesaikan tugas menggunakan algoritma sinkronisasi tambahan.

Definisi 8.2.  Pemrograman paralel adalah kemampuan untuk menyelesaikan tugas tanpa menggunakan algoritma sinkronisasi tambahan.

Anda dapat membaca lebih lanjut tentang itu di tutorial saya: Bab 8: Aliran Paralel.


1
2017-08-25 18:32