Java telah merancang beberapa kelas untuk penghitung keamanan numerik dalam multi-threading. Kelas-kelas ini disebut kelas atom.
java.util.concurrent.atomic.AtomicBoolean;java.util.concurrent.atomic.AtomicInteger;java.util.concurrent.atomic.AtomicLong;java.util.concurrent.atomic.AtomicReference;
Berikut ini adalah tes tambahan yang membandingkan AtomicInteger dan nilai int biasa dalam multi-threading, menggunakan junit4;
Kode lengkap:
paket test.java;impor java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;import org.junit.Assert;import org.junit.Before;import org.junit.Test;/** * Uji operasi kenaikan AtomicInteger dan nilai int biasa di bawah multi-threading*/kelas publik TestAtomic { // Objek kenaikan Integer Atom public static AtomicInteger counter_integer; // = new AtomicInteger(0); // Variabel bertipe int public static int count_int = 0; @Before public void setUp() {// Lakukan pekerjaan pengaturan awal sebelum semua pengujian dimulai counter_integer = new AtomicInteger(0); } @Test public void testAtomic() throw InterruptedException { // Jumlah thread yang dibuat int threadCount = 100; Berapa kali thread terafiliasi lainnya melakukan loop secara internal int loopCount = 10000600; // Mengontrol objek tambahan dari thread terafiliasi; (thread menunggu lainnya menunggu thread utama dimulai) CountDownLatch latch_1 = new CountDownLatch(1); objek dari thread utama Objek; (thread utama menunggu semua thread tambahan selesai berjalan sebelum melanjutkan) CountDownLatch latch_n = new CountDownLatch(threadCount); 0; i < threadCount; i++) { Thread thread = new AtomicIntegerThread(latch_1, latch_n, loopCount); thread.start(); long startNano = System.nanoTime(); ; // Tunggu hingga thread lain selesai latch_n.await(); // long endNano = System.nanoTime(); counter_integer.get(); // Assert.assertEquals("jumlah tidak sama dengan threadCount * loopCount, pengujian gagal", jumlah, threadCount * loopCount System.out.println("--------testAtomic( ); Diharapkan sama------------"); System.out.println("Memakan waktu: " + ((endNano - startNano) / (1000 * 1000)) + "ms" ); System.out.println("threadCount = " + (threadCount) + ";"); System.out.println("loopCount = " + (loopCount) + ";"); + (jumlah) + ";"); } @Test public void testIntAdd() throw InterruptedException { // Jumlah thread yang dibuat int threadCount = 100; Berapa kali thread terafiliasi lainnya melakukan loop secara internal int loopCount = 10000600; // Mengontrol objek tambahan dari thread terafiliasi; (thread menunggu lainnya menunggu thread utama dimulai) CountDownLatch latch_1 = new CountDownLatch(1); objek dari thread utama Objek; (thread utama menunggu semua thread tambahan selesai berjalan sebelum melanjutkan) CountDownLatch latch_n = new CountDownLatch(threadCount); 0; i < threadCount; i++) { Thread thread = new IntegerThread(latch_1, latch_n, loopCount); thread.start() } long startNano = System.nanoTime(); ); // Tunggu thread lain selesai latch_n.await(); // long endNano = System.nanoTime(); int sum = count_int; Assert.assertNotEquals( "jumlah sama dengan threadCount * loopCount, testIntAdd() pengujian gagal", sum, threadCount * loopCount); System.out.println("-------testIntAdd(); Diharapkan keduanya tidak setara- - -------"); System.out.println("Memakan waktu: " + ((endNano - startNano) / (1000*1000))+ "ms"); System.out.println("threadCount = " + (threadCount) + ";"); System.out.println("loopCount = " + (loopCount) + ";"); + (jumlah) + ";"); } // kelas thread AtomicIntegerThread extends Thread { private CountDownLatch latch = null; private CountDownLatch latchdown = null; AtomicIntegerThread(CountDownLatch latch, CountDownLatch latchdown, int loopCount) { this.latch = latch; this.latchdown = latchdown; this.loopCount = loopCount; .tunggu(); } tangkap (InterruptedException e) { e.printStackTrace(); loopCount; i++) { counter_integer.getAndIncrement(); // Notifikasi dikurangi sebesar 1 latchdown.countDown(); } // Kelas thread IntegerThread extends Thread { private CountDownLatch latch = null; ; public IntegerThread(CountDownLatch latch, CountDownLatch latchdown, int loopCount) { this.latch = latch; this.latchdown = latchdown; this.loopCount = loopCount; } @Override public void run() { // Tunggu sinkronisasi sinyal coba { this.latch.await() } catch (InterruptedException e) { e.printStackTrace(); } // for (int i = 0; i < loopCount; i++) { count_int++; } // Notifikasi dikurangi 1 latchdown.countDown();
Hasil eksekusi di PC biasa seperti berikut:
---------------testAtomic(); Diharapkan dua sama------------------Memakan waktu: 85366msthreadCount = 100;loopCount = 10000600;sum = 1000060000;-----------------testIntAdd(); Keduanya diperkirakan tidak sama-------------- ---- Memakan waktu : 1406msthreadCount = 100;loopCount = 10000600;sum = 119428988;
Terlihat dari perbedaan efisiensi antara operasi AtomicInteger dan operasi int sekitar 50-80 kali lipat. Tentu saja int sangat memakan waktu. Perbandingan ini hanya untuk memberikan referensi.
Jika ditentukan sebagai eksekusi single-threaded, maka int harus digunakan; dan efisiensi eksekusi operasi int dalam multi-threading cukup tinggi, dan hanya membutuhkan 1,5 detik untuk 1 miliar kali;
(Dengan asumsi CPU adalah 2GHz, dual-core dan 4 thread, dan maksimum teoritis adalah 8GHZ, secara teoritis terdapat 8 miliar siklus clock per detik.
Satu miliar penambahan int Java membutuhkan 1,5 detik, yaitu 12 miliar operasi. Dihitung, setiap siklus menggunakan 12 siklus CPU;
Secara pribadi, menurut saya efisiensinya bagus. Bahasa C juga memerlukan lebih dari 4 siklus clock (penilaian, eksekusi kode internal, penilaian kenaikan otomatis, lompatan)
Premisnya adalah: JVM dan CPU tidak dioptimalkan secara radikal.
)
Faktanya, efisiensi AtomicInteger tidaklah rendah. Satu miliar kali memakan waktu 80 detik, dan satu juta kali berarti sekitar seperseribu, 80 milidetik.