JavaRush /Blog Java /Random-MS /Coffee break #113. 5 perkara yang anda mungkin tidak tahu...

Coffee break #113. 5 perkara yang anda mungkin tidak tahu tentang multithreading di Jawa. 10 Sambungan JetBrains untuk Melawan Hutang Teknikal

Diterbitkan dalam kumpulan

5 Perkara Yang Anda Mungkin Tidak Tahu Mengenai Multithreading di Jawa

Sumber: DZone Thread ialah nadi kepada bahasa pengaturcaraan Java. Malah menjalankan program Hello World memerlukan utas utama. Jika perlu, kami boleh menambah urutan lain pada program jika kami mahu kod aplikasi kami menjadi lebih berfungsi dan berprestasi. Jika kita bercakap tentang pelayan web, maka ia secara serentak memproses ratusan permintaan secara serentak. Berbilang benang digunakan untuk ini. Coffee break #113.  5 perkara yang anda mungkin tidak tahu tentang multithreading di Jawa.  10 Sambungan JetBrains untuk Membanteras Hutang Teknikal - 1Benang sudah pasti berguna, tetapi bekerja dengannya boleh menjadi sukar bagi kebanyakan pembangun. Dalam artikel ini, saya akan berkongsi lima konsep multithreading yang mungkin tidak diketahui oleh pembangun baharu dan berpengalaman.

1. Perintah program dan perintah pelaksanaan tidak sepadan

Apabila kami menulis kod, kami menganggap bahawa ia akan melaksanakan dengan tepat cara kami menulisnya. Walau bagaimanapun, pada hakikatnya ini tidak berlaku. Pengkompil Java boleh mengubah susunan pelaksanaan untuk mengoptimumkannya jika ia dapat menentukan bahawa output tidak akan berubah dalam kod berbenang tunggal. Lihat coretan kod berikut:
package ca.bazlur.playground;

import java.util.concurrent.Phaser;

public class ExecutionOrderDemo {
    private static class A {
        int x = 0;
    }

    private static final A sharedData1 = new A();
    private static final A sharedData2 = new A();

    public static void main(String[] args) {
        var phaser = new Phaser(3);
        var t1 = new Thread(() -> {
            phaser.arriveAndAwaitAdvance();
            var l1 = sharedData1;
            var l2 = l1.x;
            var l3 = sharedData2;
            var l4 = l3.x;
            var l5 = l1.x;
            System.out.println("Thread 1: " + l2 + "," + l4 + "," + l5);
        });
        var t2 = new Thread(() -> {
            phaser.arriveAndAwaitAdvance();
            var l6 = sharedData1;
            l6.x = 3;
            System.out.println("Thread 2: " + l6.x);
        });
        t1.start();
        t2.start();
        phaser.arriveAndDeregister();
    }
}
Kod ini nampak mudah. Kami mempunyai dua kejadian data kongsi ( sharedData1 dan sharedData2 ) yang menggunakan dua urutan. Apabila kami melaksanakan kod tersebut, kami menjangkakan outputnya adalah seperti ini:
Thread 2: 3 Thread 1: 0,0,0
Tetapi jika anda menjalankan kod beberapa kali, anda akan melihat hasil yang berbeza:
Thread 2: 3 Thread 1: 3,0,3 Thread 2: 3 Thread 1: 0,0,3 Thread 2: 3 Thread 1: 3,3,3 Thread 2: 3 Thread 1: 0,3,0 Thread 2 : 3 Benang 1: 0,3,3
Saya tidak mengatakan bahawa semua strim ini akan bermain betul-betul seperti ini pada mesin anda, tetapi ia mungkin sepenuhnya.

2. Bilangan utas Java adalah terhad

Mencipta benang dalam Java adalah mudah. Walau bagaimanapun, ini tidak bermakna kita boleh mencipta seberapa banyak yang kita suka. Bilangan utas adalah terhad. Kita boleh mengetahui dengan mudah berapa banyak benang yang boleh kita buat pada mesin tertentu menggunakan program berikut:
package ca.bazlur.playground;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

public class Playground {
    public static void main(String[] args) {
        var counter = new AtomicInteger();
        while (true) {
            new Thread(() -> {
                int count = counter.incrementAndGet();
                System.out.println("thread count = " + count);
                LockSupport.park();
            }).start();
        }
    }
}
Program di atas sangat mudah. Ia mencipta utas dalam gelung dan kemudian meletakkannya, yang bermaksud utas itu dilumpuhkan untuk kegunaan masa hadapan tetapi melakukan panggilan sistem dan memperuntukkan memori. Program ini terus mencipta benang sehingga ia tidak dapat mencipta lagi, dan kemudian membuang pengecualian. Kami berminat dengan nombor yang akan kami terima sehingga program mengeluarkan pengecualian. Pada komputer saya, saya hanya dapat mencipta 4065 utas.

3. Terlalu banyak benang tidak menjamin prestasi yang lebih baik

Adalah naif untuk mempercayai bahawa menjadikan benang mudah dalam Java akan meningkatkan prestasi aplikasi. Malangnya, andaian ini salah dengan model multithreading tradisional kami yang disediakan Java hari ini. Malah, terlalu banyak benang boleh mengurangkan prestasi aplikasi. Mari kita tanya soalan ini dahulu: apakah bilangan maksimum benang yang boleh kita cipta untuk memaksimumkan prestasi aplikasi? Nah, jawapannya tidak semudah itu. Ia sangat bergantung pada jenis kerja yang kita lakukan. Jika kita mempunyai berbilang tugas bebas, semuanya adalah pengiraan dan tidak menyekat sebarang sumber luaran, maka mempunyai sejumlah besar utas tidak akan meningkatkan prestasi dengan banyak. Sebaliknya, jika kita mempunyai pemproses 8 teras, bilangan benang yang optimum boleh jadi (8 + 1). Dalam kes sedemikian, kita boleh bergantung pada benang selari yang diperkenalkan dalam Java 8. Secara lalai, benang selari menggunakan kolam Fork/Join yang dikongsi. Ia mencipta benang yang sama dengan bilangan pemproses yang tersedia, yang cukup untuk mereka bekerja secara intensif. Menambah lebih banyak utas pada kerja intensif CPU yang tiada apa-apa yang disekat tidak akan meningkatkan prestasi. Sebaliknya, kita hanya akan membazirkan sumber. Catatan. Sebab untuk mempunyai benang tambahan ialah walaupun benang intensif pengiraan kadangkala menyebabkan kerosakan halaman atau digantung atas sebab lain. (Lihat: Java Parallelism in Practice , Brian Goetz, halaman 170) Walau bagaimanapun, anggap, sebagai contoh, bahawa tugasan terikat I/O. Dalam kes ini, mereka bergantung pada komunikasi luaran (cth. pangkalan data, API lain), jadi bilangan utas yang lebih besar masuk akal. Sebabnya ialah apabila thread sedang menunggu pada Rest API, thread lain boleh terus berfungsi. Sekarang kita boleh bertanya lagi, berapa banyak benang yang terlalu banyak untuk kes sedemikian? Terpulang. Tiada nombor sempurna yang sesuai dengan semua kes. Oleh itu, kita mesti melakukan ujian yang mencukupi untuk mengetahui perkara yang paling sesuai untuk beban kerja dan aplikasi khusus kita. Dalam senario yang paling biasa, kami biasanya mempunyai set tugasan yang bercampur-campur. Dan dalam kes sedemikian, perkara akan selesai. Dalam bukunya "Java Concurrency in Practice," Brian Goetz mencadangkan formula yang boleh kita gunakan dalam kebanyakan kes. Bilangan utas = Bilangan Teras Tersedia * (1 + Masa menunggu / Masa perkhidmatan) Masa menunggu boleh menjadi IO, seperti menunggu respons HTTP, memperoleh kunci dan sebagainya. Masa Perkhidmatan(Masa perkhidmatan) ialah masa pengiraan, seperti memproses respons HTTP, marshaling/unmarshaling, dan sebagainya. Sebagai contoh, aplikasi memanggil API dan kemudian memprosesnya. Jika kita mempunyai 8 pemproses pada pelayan aplikasi, purata masa tindak balas API ialah 100ms, dan masa pemprosesan respons ialah 20ms, maka saiz benang yang ideal ialah:
N = 8 * ( 1 + 100/20) = 48
Walau bagaimanapun, ini adalah penyederhanaan yang berlebihan; ujian yang mencukupi sentiasa kritikal untuk menentukan nombor.

4. Multithreading bukan selari

Kadangkala kami menggunakan multithreading dan paralelisme secara bergantian, tetapi ini tidak lagi relevan sepenuhnya. Walaupun di Jawa kita mencapai kedua-duanya menggunakan benang, ia adalah dua perkara yang berbeza. "Dalam pengaturcaraan, multithreading adalah kes khas tanpa mengira proses yang berjalan, dan selari ialah pelaksanaan serentak pengiraan (mungkin berkaitan). Multithreading adalah mengenai berinteraksi dengan banyak perkara pada masa yang sama. Concurrency melakukan banyak perkara pada masa yang sama.” Definisi di atas yang diberikan oleh Rob Pike agak tepat. Katakan kita mempunyai tugasan bebas sepenuhnya, dan ia boleh dikira secara berasingan. Dalam kes ini, tugasan ini dipanggil selari dan boleh dilaksanakan dengan kolam Fork/Join atau benang selari. Sebaliknya, jika kita mempunyai banyak tugas, sebahagian daripadanya mungkin bergantung kepada yang lain. Cara kita mengarang dan menyusun dipanggil multithreading. Ia mempunyai kaitan dengan struktur. Kita mungkin mahu melaksanakan beberapa tugasan secara serentak untuk mencapai hasil tertentu, tanpa perlu menyelesaikannya dengan lebih cepat.

5. Project Loom membolehkan kami mencipta berjuta-juta benang

Dalam perkara sebelumnya, saya berhujah bahawa mempunyai lebih banyak benang tidak bermakna prestasi aplikasi yang lebih baik. Walau bagaimanapun, dalam era perkhidmatan mikro, kami berinteraksi dengan terlalu banyak perkhidmatan untuk menyelesaikan sebarang kerja tertentu. Dalam senario sedemikian, benang kekal dalam keadaan tersekat pada kebanyakan masa. Walaupun OS moden boleh mengendalikan berjuta-juta soket terbuka, kami tidak boleh membuka banyak saluran komunikasi kerana kami dihadkan oleh bilangan utas. Tetapi bagaimana jika anda mencipta berjuta-juta benang, dan setiap daripadanya menggunakan soket terbuka untuk berkomunikasi dengan dunia luar? Ini pasti akan meningkatkan daya pemprosesan aplikasi kami. Untuk menyokong idea ini, terdapat satu inisiatif dalam Java yang dipanggil Project Loom. Menggunakannya, kita boleh mencipta berjuta-juta benang maya. Contohnya, menggunakan coretan kod berikut, saya dapat mencipta 4.5 juta utas pada mesin saya.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

public class Main {
    public static void main(String[] args) {
        var counter = new AtomicInteger();

        // 4_576_279
        while (true) {
            Thread.startVirtualThread(() -> {
                int count = counter.incrementAndGet();
                System.out.println("thread count = " + count);
                LockSupport.park();
            });
        }
    }
}
Untuk menjalankan program ini, anda mesti memasang Java 18, yang boleh dimuat turun di sini . Anda boleh menjalankan kod menggunakan arahan berikut: java --source 18 --enable-preview Main.java

10 Sambungan JetBrains untuk Melawan Hutang Teknikal

Sumber: DZone Banyak pasukan pembangunan merasakan tekanan yang besar untuk memenuhi tarikh akhir. Oleh sebab itu, mereka sering tidak mempunyai masa yang mencukupi untuk membetulkan dan membersihkan pangkalan kod mereka. Kadang-kadang dalam situasi ini, hutang teknikal cepat terkumpul. Sambungan editor boleh membantu menyelesaikan masalah ini. Mari kita lihat 10 sambungan JetBrains terbaik untuk memerangi hutang teknikal (dengan sokongan Java). Coffee break #113.  5 perkara yang anda mungkin tidak tahu tentang multithreading di Jawa.  10 Sambungan JetBrains untuk Melawan Hutang Teknikal - 2

Pemfaktoran semula dan alat hutang teknikal

1. RefactorInsight

RefactorInsight meningkatkan keterlihatan perubahan kod dalam IDE dengan menyediakan maklumat tentang pemfaktoran semula.
  1. Sambungan mentakrifkan pemfaktoran semula dalam permintaan gabungan.
  2. Komit markah yang mengandungi pemfaktoran semula.
  3. Membantu dalam melihat pemfaktoran semula mana-mana komit tertentu yang dipilih dalam tab Log Git.
  4. Menunjukkan sejarah pemfaktoran semula kelas, kaedah dan medan.

2. Penjejak Isu Saiz Langkah dalam IDE

Stepsize ialah penjejak isu yang bagus untuk pembangun. Sambungan ini membantu jurutera bukan sahaja mencipta TODO dan komen kod yang lebih baik, tetapi juga mengutamakan hutang teknikal, pemfaktoran semula dan seumpamanya:
  1. Stepsize membolehkan anda membuat dan melihat tugasan dalam kod terus dalam editor.
  2. Cari isu yang mempengaruhi ciri yang sedang anda usahakan.
  3. Tambahkan isu pada larian pecut anda menggunakan penyepaduan Jira, Asana, Linear, Azure DevOps dan GitHub.

3. Aliran Kod Peninggalan Baharu

New Relic CodeStream ialah platform kerjasama pembangun untuk membincangkan dan menyemak kod. Ia menyokong permintaan tarik daripada GitHub, BitBucket dan GitLab, pengurusan isu daripada Jira, Trello, Asana dan 9 yang lain, dan menyediakan perbincangan kod, mengikat semuanya bersama-sama.
  1. Buat, semak dan gabungkan permintaan tarik dalam GitHub.
  2. Dapatkan maklum balas tentang kerja yang sedang dijalankan dengan semakan kod awal.
  3. Membincangkan masalah kod dengan rakan sepasukan.

TODO dan komen

4. Penyerlah Komen

Pemalam ini membolehkan anda membuat penyerlahan tersuai bagi baris ulasan dan kata kunci bahasa. Pemalam ini juga mempunyai keupayaan untuk menentukan token tersuai untuk menyerlahkan baris ulasan.

5. Komen yang Lebih Baik

Sambungan Komen Lebih Baik membantu anda membuat ulasan yang lebih jelas dalam kod anda. Dengan sambungan ini, anda akan dapat mengklasifikasikan anotasi anda kepada:
  1. Makluman.
  2. Permintaan.
  3. TODO.
  4. Detik asas.

Pepijat dan kelemahan keselamatan

6.SonarLint _

SonarLint membolehkan anda menyelesaikan masalah kod sebelum ia timbul. Ia juga boleh digunakan sebagai penyemak ejaan. SonarLint menyerlahkan pepijat dan kelemahan keselamatan semasa anda mengekod, dengan arahan pemulihan yang jelas supaya anda boleh membetulkannya sebelum kod dilakukan.

7. SpotBugs

Plugin SpotBugs menyediakan analisis bytecode statik untuk mencari pepijat dalam kod Java daripada IntelliJ IDEA. SpotBugs ialah alat pengesanan kecacatan untuk Java yang menggunakan analisis statik untuk mencari lebih 400 corak pepijat seperti penyahrujukan penunjuk nol, gelung rekursif tak terhingga, penyalahgunaan perpustakaan Java dan kebuntuan. SpotBugs boleh mengenal pasti beratus-ratus kecacatan serius dalam aplikasi besar (biasanya kira-kira 1 kecacatan setiap 1000-2000 baris kenyataan mentah tanpa ulasan).

8. Pengimbas Kerentanan Snyk

Pengimbas Kerentanan Snyk membantu anda mencari dan membetulkan kelemahan keselamatan dan isu kualiti kod dalam projek anda.
  1. Mencari dan menyelesaikan masalah keselamatan.
  2. Lihat senarai pelbagai jenis masalah, dibahagikan kepada kategori.
  3. Memaparkan petua penyelesaian masalah.

9. Pencari Aksara Lebar Sifar

Pemalam ini mempertingkatkan pemeriksaan dan pengesanan ralat yang sukar ditemui berkaitan dengan aksara lebar sifar yang tidak kelihatan dalam kod sumber dan sumber. Apabila menggunakan, pastikan bahawa semakan "Katak unikod lebar sifar" didayakan.

10. CodeMR _

CodeMR ialah kualiti perisian dan alat analisis kod statik yang membantu syarikat perisian membangunkan kod dan program yang lebih baik. CodeMR menggambarkan metrik kod dan atribut kualiti peringkat tinggi (gandingan, kerumitan, perpaduan dan saiz) dalam pelbagai paparan seperti Struktur Pakej, TreeMap, Sunburst, Ketergantungan dan Paparan Graf.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION