CodeGym/Java Blog/Acak/Menjelajahi pertanyaan dan jawaban dari wawancara kerja u...
John Squirrels
Level 41
San Francisco

Menjelajahi pertanyaan dan jawaban dari wawancara kerja untuk posisi pengembang Java. Bagian 12

Dipublikasikan di grup Acak
anggota
Hai! Pengetahuan adalah kekuatan. Semakin banyak pengetahuan yang Anda miliki pada wawancara pertama, Anda akan semakin percaya diri. Menjelajahi pertanyaan dan jawaban dari wawancara kerja untuk posisi pengembang Java.  Bagian 12 - 1Jika Anda membawa otak besar yang penuh pengetahuan, pewawancara Anda akan sulit membingungkan Anda dan kemungkinan besar akan terkejut. Jadi tanpa basa-basi lagi, hari ini kami akan terus memperkuat landasan teori Anda dengan mengulas pertanyaan untuk pengembang Java.

103. Aturan apa yang berlaku untuk pemeriksaan pengecualian selama pewarisan?

Jika saya memahami pertanyaannya dengan benar, mereka bertanya tentang aturan untuk bekerja dengan pengecualian selama pewarisan. Aturan yang relevan adalah sebagai berikut:
  • Metode yang ditimpa atau diimplementasikan dalam turunan/implementasi tidak dapat menampilkan pengecualian tercentang yang hierarkinya lebih tinggi daripada pengecualian dalam metode superkelas/antarmuka.
Misalnya, kita mempunyai antarmuka Animal dengan metode yang memunculkan IOException :
public interface Animal {
   void speak() throws IOException;
}
Saat mengimplementasikan antarmuka ini, kita tidak bisa mengekspos pengecualian throwable yang lebih umum (misalnya Exception , Throwable ), namun kita bisa mengganti pengecualian yang ada dengan subkelas, seperti FileNotFoundException :
public class Cat implements Animal {
   @Override
   public void speak() throws FileNotFoundException {
// Some implementation
   }
}
  • Klausa throws dari konstruktor subkelas harus menyertakan semua kelas pengecualian yang dilemparkan oleh konstruktor superkelas yang dipanggil untuk membuat objek.
Misalkan konstruktor kelas Animal memberikan banyak pengecualian:
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Kemudian konstruktor subkelas juga harus membuangnya:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
Atau, seperti halnya metode, Anda dapat menentukan pengecualian yang berbeda dan lebih umum. Dalam kasus kita, kita dapat mengindikasikan Exception karena lebih umum dan merupakan nenek moyang dari ketiga pengecualian yang ditunjukkan dalam superkelas:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Bisakah Anda menulis beberapa kode yang blok akhirnya tidak dieksekusi?

Pertama, mari kita ingat apa akhirnya . Sebelumnya, kita telah memeriksa mekanisme penangkapan pengecualian: blok percobaan menunjukkan di mana pengecualian akan ditangkap, dan blok tangkapan adalah kode yang akan dipanggil ketika pengecualian terkait ditangkap . Blok kode ketiga yang ditandai dengan kata kunci akhirnya dapat menggantikan atau muncul setelah blok catch. Ide di balik blok ini adalah bahwa kodenya selalu dieksekusi terlepas dari apa yang terjadi di blok coba atau tangkap (terlepas dari apakah ada pengecualian atau tidak). Contoh di mana blok ini tidak dieksekusi jarang terjadi dan tidak normal. Contoh paling sederhana adalah ketika System.exit(0) dipanggil sebelum blok akhirnya, sehingga menghentikan program:
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("This message will not be printed on the console");
}
Ada juga beberapa situasi lain di mana blok akhirnya tidak berjalan:
  • Misalnya, penghentian program yang tidak normal yang disebabkan oleh kesalahan sistem yang kritis, atau beberapa kesalahan yang menyebabkan aplikasi mogok (misalnya, StackOverflowError , yang terjadi ketika tumpukan aplikasi meluap).

  • Situasi lainnya adalah ketika thread daemon memasuki blok try-finally , namun kemudian thread utama program berakhir. Lagi pula, thread daemon ditujukan untuk pekerjaan latar belakang yang bukan merupakan prioritas tinggi atau wajib, sehingga aplikasi tidak akan menunggu sampai thread tersebut selesai.

  • Contoh yang paling tidak masuk akal adalah perulangan tanpa akhir di dalam blok coba atau tangkap — begitu masuk, sebuah thread akan terjebak di sana selamanya:

    try {
       while (true) {
       }
    } finally {
       System.out.println("This message will not be printed on the console");
    }
Pertanyaan ini sangat populer dalam wawancara pengembang junior, jadi ada baiknya mengingat beberapa situasi luar biasa ini. Menjelajahi pertanyaan dan jawaban dari wawancara kerja untuk posisi pengembang Java.  Bagian 12 - 2

105. Tuliskan contoh di mana Anda menangani beberapa pengecualian dalam satu blok tangkapan.

1) Saya tidak yakin pertanyaan ini ditanyakan dengan benar. Sejauh yang saya mengerti, pertanyaan ini mengacu pada beberapa blok tangkapan dan satu percobaan :
try {
  throw new FileNotFoundException();
} catch (FileNotFoundException e) {
   System.out.print("Oops! There was an exception: " + e);
} catch (IOException e) {
   System.out.print("Oops! There was an exception: " + e);
} catch (Exception e) {
   System.out.print("Oops! There was an exception: " + e);
}
Jika pengecualian dilemparkan ke dalam blok coba , maka blok tangkapan yang terkait akan mencoba menangkapnya, secara berurutan dari atas ke bawah. Setelah pengecualian cocok dengan salah satu blok tangkapan , blok yang tersisa tidak lagi dapat menangkap dan menanganinya. Ini semua berarti bahwa pengecualian yang lebih sempit disusun di atas pengecualian yang lebih umum dalam kumpulan blok tangkapan . Misalnya, jika blok tangkapan pertama kita menangkap kelas Exception , maka blok berikutnya tidak akan menangkap pengecualian yang dicentang (yaitu, blok yang tersisa dengan subkelas Exception tidak akan berguna sama sekali). 2) Atau mungkin pertanyaannya ditanyakan dengan benar. Dalam hal ini, kami dapat menangani pengecualian sebagai berikut:
try {
  throw new NullPointerException();
} catch (Exception e) {
   if (e instanceof FileNotFoundException) {
       // Some handling that involves a narrowing type conversion: (FileNotFoundException)e
   } else if (e instanceof ArithmeticException) {
       // Some handling that involves a narrowing type conversion: (ArithmeticException)e
   } else if(e instanceof NullPointerException) {
       // Some handling that involves a narrowing type conversion: (NullPointerException)e
   }
Setelah menggunakan catch untuk menangkap pengecualian, kami kemudian mencoba menemukan tipe spesifiknya dengan menggunakan operator instanceof , yang memeriksa apakah suatu objek termasuk dalam tipe tertentu. Hal ini memungkinkan kami melakukan konversi tipe penyempitan dengan percaya diri tanpa takut akan konsekuensi negatif. Kita dapat menerapkan pendekatan mana pun dalam situasi yang sama. Saya menyatakan keraguan tentang pertanyaan itu hanya karena saya tidak menyebut opsi kedua sebagai pendekatan yang baik. Dalam pengalaman saya, saya belum pernah menemukannya, dan pendekatan pertama yang melibatkan banyak blok tangkapan tersebar luas.

106. Operator mana yang mengizinkan Anda melemparkan pengecualian secara paksa? Tulis sebuah contoh

Saya sudah menggunakannya beberapa kali pada contoh di atas, tapi saya akan mengulanginya sekali lagi: kata kunci throw . Contoh pelemparan pengecualian secara manual:
throw new NullPointerException();

107. Bisakah metode utama mengeluarkan pengecualian? Jika ya, lalu kemana perginya?

Pertama-tama, saya ingin mencatat bahwa metode utama tidak lebih dari metode biasa. Ya, ini dipanggil oleh mesin virtual untuk memulai eksekusi suatu program, tetapi lebih dari itu, dapat dipanggil dari kode lain. Artinya, ini juga tunduk pada aturan umum tentang menunjukkan pengecualian yang dicentang setelah kata kunci throws :
public static void main(String[] args) throws IOException {
Oleh karena itu, hal ini dapat menimbulkan pengecualian. Ketika main dipanggil sebagai titik awal program (bukan dengan metode lain), maka pengecualian apa pun yang dilontarkannya akan ditangani oleh UncaughtExceptionHandler . Setiap thread memiliki satu handler (yaitu, ada satu handler di setiap thread). Jika perlu, Anda dapat membuat handler Anda sendiri dan mengaturnya dengan memanggil metode public static void main(String[] args) throws IOException {setDefaultUncaughtExceptionHandler pada public static void main(String[] args) throws IOException {Thread object.

Multithread

Menjelajahi pertanyaan dan jawaban dari wawancara kerja untuk posisi pengembang Java.  Bagian 12 - 3

108. Mekanisme apa untuk bekerja di lingkungan multithread yang Anda ketahui?

Mekanisme dasar untuk multithreading di Java adalah:
  • Kata kunci tersinkronisasi , yaitu cara thread mengunci suatu metode/blok ketika masuk, sehingga mencegah masuknya thread lain.

  • Kata kunci volatil memastikan akses yang konsisten ke variabel yang diakses oleh thread berbeda. Artinya, ketika pengubah ini diterapkan pada suatu variabel, semua operasi untuk menetapkan dan membaca variabel tersebut menjadi atomik. Dengan kata lain, thread tidak akan menyalin variabel ke memori lokalnya dan mengubahnya. Mereka akan mengubah nilai aslinya.

  • Runnable — Kita dapat mengimplementasikan antarmuka ini (yang terdiri dari satu metode run() ) di beberapa kelas:

    public class CustomRunnable implements Runnable {
       @Override
       public void run() {
           // Some logic
       }
    }

    Dan setelah kita membuat objek dari kelas itu, kita bisa memulai thread baru dengan meneruskan objek kita ke konstruktor Thread dan kemudian memanggil metode start() :

    Runnable runnable = new CustomRunnable();
    new Thread(runnable).start();

    Metode start menjalankan metode run() yang diimplementasikan pada thread terpisah.

  • Thread — Kita dapat mewarisi kelas ini dan mengganti metode eksekusinya :

    public class CustomThread extends Thread {
       @Override
       public void run() {
           // Some logic
       }
    }

    Kita bisa memulai thread baru dengan membuat objek kelas ini dan kemudian memanggil metode start() :

    new CustomThread().start();

  • Konkurensi — Ini adalah paket alat untuk bekerja di lingkungan multithread.

    Terdiri dari:

    • Koleksi Bersamaan — Ini adalah kumpulan koleksi yang dibuat secara eksplisit untuk bekerja di lingkungan multithread.

    • Antrian — Antrean khusus untuk lingkungan multithread (pemblokiran dan non-pemblokiran).

    • Sinkronisasi — Ini adalah utilitas khusus untuk bekerja di lingkungan multithread.

    • Pelaksana — Mekanisme untuk membuat kumpulan thread.

    • Kunci — Mekanisme sinkronisasi thread yang lebih fleksibel daripada yang standar (disinkronkan, tunggu, beri tahu, beri tahuSemua).

    • Atomics — Kelas yang dioptimalkan untuk multithreading. Setiap operasinya bersifat atomik.

109. Beritahu kami tentang sinkronisasi antar thread. Untuk apa metode wait(), notify(), notifyAll(), dan join()?

Sinkronisasi antar thread adalah tentang kata kunci yang disinkronkan . Pengubah ini dapat ditempatkan langsung di blok:
synchronized (Main.class) {
   // Some logic
}
Atau langsung di tanda tangan metode:
public synchronized void move() {
   // Some logic }
Seperti yang saya katakan sebelumnya, sinkronisasi adalah mekanisme untuk mengunci suatu blok/metode ke thread lain begitu satu thread masuk. Mari kita bayangkan blok kode/metode sebagai sebuah ruangan. Beberapa benang mendekati ruangan, memasukinya, dan mengunci pintu dengan kuncinya. Ketika thread lain mendekati ruangan, mereka melihat bahwa pintu terkunci dan menunggu di dekatnya sampai ruangan tersedia. Setelah thread pertama selesai dengan urusannya di dalam ruangan, ia membuka kunci pintu, meninggalkan ruangan, dan melepaskan kuncinya. Saya telah menyebutkan sebuah kunci beberapa kali karena suatu alasan — karena sesuatu yang analog memang ada. Ini adalah objek khusus yang mempunyai keadaan sibuk/bebas. Setiap objek di Java memiliki objek seperti itu, jadi ketika kita menggunakan blok tersinkronisasi , kita perlu menggunakan tanda kurung untuk menunjukkan objek yang mutexnya akan dikunci:
Cat cat = new Cat();
synchronized (cat) {
   // Some logic
}
Kita juga dapat menggunakan mutex yang terkait dengan suatu kelas, seperti yang saya lakukan pada contoh pertama ( Main.class ). Lagi pula, ketika kita menggunakan sinkronisasi pada suatu metode, kita tidak menentukan objek yang ingin kita kunci, bukan? Dalam hal ini, untuk metode non-statis, mutex yang akan dikunci adalah objek ini , yaitu objek kelas saat ini. Untuk metode statis, mutex yang terkait dengan kelas saat ini ( this.getClass(); ) dikunci. wait() adalah metode yang membebaskan mutex dan menempatkan thread saat ini ke status menunggu, seolah-olah menempel pada monitor saat ini (seperti jangkar). Oleh karena itu, metode ini hanya dapat dipanggil dari blok atau metode yang disinkronkan . Kalau tidak, tunggu apa lagi dan apa yang akan dirilis?). Perhatikan juga bahwa ini adalah metode kelas Object . Ya, bukan hanya satu, tapi tiga:
  • wait() menempatkan thread saat ini ke dalam status menunggu hingga thread lain memanggil metode notify() atau notifyAll() pada objek ini (kita akan membicarakan metode ini nanti).

  • wait(long timeout) menempatkan thread saat ini ke dalam status menunggu hingga thread lain memanggil metode notify() atau notifyAll() pada objek ini atau interval waktu yang ditentukan oleh batas waktu berakhir.

  • wait(long timeout, int nanos) seperti metode sebelumnya, tetapi di sini nanos memungkinkan Anda menentukan nanodetik (batas waktu yang lebih tepat).

  • notify() memungkinkan Anda membangunkan satu thread acak yang menunggu di blok sinkronisasi saat ini. Sekali lagi, metode ini hanya dapat dipanggil dalam blok atau metode yang disinkronkan (lagipula, di tempat lain tidak akan ada orang yang bangun).

  • notifyAll() membangunkan semua thread yang menunggu di monitor saat ini (juga hanya digunakan dalam blok atau metode yang disinkronkan ).

110. Bagaimana cara menghentikan thread?

Hal pertama yang harus dikatakan di sini adalah ketika run() berjalan hingga selesai, thread akan berakhir secara otomatis. Namun terkadang kita ingin mematikan thread lebih cepat dari jadwal, sebelum metode tersebut dilakukan. Jadi apa yang kita lakukan? Mungkin kita bisa menggunakan metode stop() pada objek Thread ? Tidak! Metode tersebut sudah tidak digunakan lagi dan dapat menyebabkan sistem crash. Menjelajahi pertanyaan dan jawaban dari wawancara kerja untuk posisi pengembang Java.  Bagian 12 - 4Lalu bagaimana? Ada dua cara untuk melakukan ini: Pertama , gunakan flag boolean internalnya. Mari kita lihat sebuah contoh. Kami memiliki implementasi thread yang seharusnya menampilkan frasa tertentu di layar hingga thread berhenti sepenuhnya:
public class CustomThread extends Thread {
private boolean isActive;

   public CustomThread() {
       this.isActive = true;
   }

   @Override
   public void run() {
       {
           while (isActive) {
               System.out.println("The thread is executing some logic...");
           }
           System.out.println("The thread stopped!");
       }
   }

   public void stopRunningThread() {
       isActive = false;
   }
}
Memanggil metode stopRunningThread() akan menyetel tanda internal ke false, sehingga menyebabkan metode run() berhenti. Sebut saja main :
System.out.println("Program starting...");
CustomThread thread = new CustomThread();
thread.start();
Thread.sleep(3);
// As long as our main thread is asleep, our CustomThread runs and prints its message on the console
thread.stopRunningThread();
System.out.println("Program stopping...");
Hasilnya, kita akan melihat sesuatu seperti ini di konsol:
Program dimulai... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Utas menjalankan beberapa logika... Program berhenti... Utas berhenti!
Itu berarti thread kita dimulai, mencetak beberapa pesan di konsol, dan kemudian berhasil dihentikan. Perhatikan bahwa jumlah pesan yang ditampilkan akan bervariasi dari satu peluncuran ke peluncuran lainnya. Dan terkadang thread bantu mungkin tidak menampilkan apa pun. Perilaku spesifiknya bergantung pada berapa lama thread utama tertidur. Semakin lama ia tidur, semakin kecil kemungkinan thread tambahan tidak dapat menampilkan apa pun. Dengan waktu tidur 1 ms, Anda hampir tidak akan pernah melihat pesan-pesan tersebut. Namun jika Anda menyetelnya ke 20 ms, maka pesan hampir selalu ditampilkan. Ketika waktu tidurnya singkat, thread tidak punya waktu untuk memulai dan melakukan tugasnya. Sebaliknya, hal itu akan segera dihentikan. Cara kedua adalah dengan menggunakan metode interupsi() pada objek Thread . Ini mengembalikan nilai bendera interupsi internal, yang secara default adalah false . Atau metode interupsi()- nya , yang menyetel tanda ini ke true (bila tandanya benar , thread akan berhenti berjalan). Mari kita lihat sebuah contoh:
public class CustomThread extends Thread {

   @Override
   public void run() {
       {
           while (!Thread.interrupted()) {
               System.out.println("The thread is executing some logic...");
           }
           System.out.println("The thread stopped!");
       }
   }
}
Berjalan di utama :
System.out.println("Program starting...");
Thread thread = new CustomThread();
thread.start();
Thread.sleep(3);
thread.interrupt();
System.out.println("Program stopping...");
Hasil dari menjalankan ini sama seperti pada kasus pertama, tapi saya lebih menyukai pendekatan ini: kami menulis lebih sedikit kode dan menggunakan lebih banyak fungsi standar yang sudah jadi. Baiklah, itu saja untuk hari ini!
Komentar
  • Populer
  • Baru
  • Lama
Anda harus login untuk memberikan komentar
Halaman ini belum memiliki komentar