CodeGym/Java Blog/Random/Paggalugad ng mga tanong at sagot mula sa isang job inter...
John Squirrels
Antas
San Francisco

Paggalugad ng mga tanong at sagot mula sa isang job interview para sa isang Java developer position. Bahagi 12

Nai-publish sa grupo
Hi! Kaalaman ay kapangyarihan. Ang mas maraming kaalaman na mayroon ka sa iyong unang pakikipanayam, mas tiwala ang iyong mararamdaman. Paggalugad ng mga tanong at sagot mula sa isang job interview para sa isang Java developer position.  Bahagi 12 - 1Kung magdadala ka ng isang malaking utak na puno ng kaalaman, ang iyong tagapanayam ay mahihirapang lituhin ka at malamang na mabigla. Kaya nang walang karagdagang ado, ngayon ay patuloy naming palalakasin ang iyong teoretikal na base sa pamamagitan ng pagsusuri sa mga tanong para sa isang developer ng Java.

103. Anong mga tuntunin ang nalalapat sa pagsuri sa eksepsiyon sa panahon ng pagmamana?

Kung naiintindihan ko nang tama ang tanong, nagtatanong sila tungkol sa mga patakaran para sa pagtatrabaho nang may mga pagbubukod sa panahon ng mana. Ang mga kaugnay na tuntunin ay ang mga sumusunod:
  • Ang isang na-override o ipinatupad na paraan sa isang descendant/implementation ay hindi maaaring magtapon ng mga naka-check na exception na mas mataas sa hierarchy kaysa sa mga exception sa isang superclass/interface na paraan.
Halimbawa, ipagpalagay na mayroon kaming ilang interface ng Animal na may isang pamamaraan na naghagis ng isang IOException :
public interface Animal {
   void speak() throws IOException;
}
Kapag ipinapatupad ang interface na ito, hindi namin maaaring ilantad ang isang mas pangkalahatang throwable exception (eg Exception , Throwable ), ngunit maaari naming palitan ang umiiral na exception ng subclass, tulad ng FileNotFoundException :
public class Cat implements Animal {
   @Override
   public void speak() throws FileNotFoundException {
// Some implementation
   }
}
  • Ang throws clause ng subclass constructor ay dapat isama ang lahat ng exception classes na itinapon ng superclass constructor na tinatawag na gumawa ng object.
Ipagpalagay na ang tagabuo ng klase ng Animal ay nagtatapon ng maraming mga pagbubukod:
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Pagkatapos ay dapat ding itapon ng isang subclass constructor ang mga ito:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
O, tulad ng sa mga pamamaraan, maaari mong tukuyin ang iba't ibang, mas pangkalahatang mga pagbubukod. Sa aming kaso, maaari naming ipahiwatig ang Exception , dahil ito ay mas pangkalahatan at isang karaniwang ninuno ng lahat ng tatlong mga pagbubukod na ipinahiwatig sa superclass:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Maaari ka bang magsulat ng ilang code kung saan ang panghuling bloke ay hindi naisakatuparan?

Una, tandaan natin kung ano ang wakas . Mas maaga, sinuri namin ang exception catching mechanism: ang isang try block ay tumutukoy kung saan ang mga exception ay mahuhuli, at ang catch block (mga) ay ang code na ipapatawag kapag may nahuli na kaukulang exception. Ang ikatlong bloke ng code na minarkahan ng panghuling keyword ay maaaring palitan o dumating pagkatapos ng mga catch block. Ang ideya sa likod ng block na ito ay ang code nito ay palaging isinasagawa anuman ang mangyayari sa isang try or catch block (hindi alintana kung mayroong exception o wala). Ang mga pagkakataon, kung saan ang block na ito ay hindi naisakatuparan ay madalang at sila ay abnormal. Ang pinakasimpleng halimbawa ay kapag ang System.exit(0) ay tinawag bago ang panghuling pag-block, sa gayon ay tinatapos ang programa:
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("This message will not be printed on the console");
}
Mayroon ding ilang iba pang mga sitwasyon kung saan ang panghuling bloke ay hindi tatakbo:
  • Halimbawa, isang abnormal na pagwawakas ng program na dulot ng mga kritikal na error sa system, o ilang error na nagiging sanhi ng pag-crash ng application (halimbawa, ang StackOverflowError , na nangyayari kapag ang application stack ay umapaw).

  • Ang isa pang sitwasyon ay kapag ang isang daemon thread ay pumasok sa isang try-finally block, ngunit pagkatapos ay ang pangunahing thread ng programa ay magwawakas. Pagkatapos ng lahat, ang mga daemon thread ay para sa trabaho sa background na hindi mataas ang priyoridad o sapilitan, kaya hindi na hihintayin ng application na matapos ang mga ito.

  • Ang pinakawalang isip na halimbawa ay isang walang katapusang loop sa loob ng try or catch block — kapag nasa loob na, isang thread ang mananatili doon magpakailanman:

    try {
       while (true) {
       }
    } finally {
       System.out.println("This message will not be printed on the console");
    }
Ang tanong na ito ay napakasikat sa mga panayam ng junior developer, kaya magandang ideya na tandaan ang ilan sa mga pambihirang sitwasyong ito. Paggalugad ng mga tanong at sagot mula sa isang job interview para sa isang Java developer position.  Bahagi 12 - 2

105. Sumulat ng isang halimbawa kung saan pinangangasiwaan mo ang maramihang mga pagbubukod sa iisang catch block.

1) Hindi ako siguradong tama ang tanong na ito. Sa pagkakaintindi ko, ang tanong na ito ay tumutukoy sa ilang mga catch block at isang pagsubok :
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);
}
Kung ang isang exception ay itinapon sa isang try block, pagkatapos ay ang mga nauugnay na catch block ay susubukang saluhin ito, nang sunud-sunod mula sa itaas hanggang sa ibaba. Kapag ang exception ay tumugma sa isa sa mga catch block, ang anumang natitirang block ay hindi na mahuli at mahawakan ito. Nangangahulugan ito na ang mas makitid na mga pagbubukod ay nakaayos sa itaas ng mga mas pangkalahatan sa hanay ng mga bloke ng catch . Halimbawa, kung nahuli ng aming unang catch block ang Exception class, ang anumang kasunod na block ay hindi makakahuli ng mga naka-check na exception (iyon ay, ang natitirang mga block na may mga subclass ng Exception ay magiging ganap na walang silbi). 2) O marahil ang tanong ay naitanong nang tama. Sa kasong iyon, maaari naming pangasiwaan ang mga pagbubukod tulad ng sumusunod:
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
   }
Pagkatapos gumamit ng catch para makahuli ng exception, susubukan naming tuklasin ang partikular na uri nito sa pamamagitan ng paggamit ng instanceof operator, na nagsusuri kung ang isang bagay ay kabilang sa isang partikular na uri. Nagbibigay-daan ito sa amin na kumpiyansa na magsagawa ng pagpapalit ng uri ng conversion nang walang takot sa mga negatibong kahihinatnan. Maaari naming ilapat ang alinman sa diskarte sa parehong sitwasyon. Nagpahayag ako ng pag-aalinlangan tungkol sa tanong dahil hindi ko tatawagin ang pangalawang opsyon na isang mahusay na diskarte. Sa aking karanasan, hindi ko pa ito nakatagpo, at ang unang diskarte na kinasasangkutan ng maraming catch block ay laganap.

106. Aling operator ang nagpapahintulot sa iyo na pilitin ang isang exception na ihagis? Sumulat ng isang halimbawa

Nagamit ko na ito ng ilang beses sa mga halimbawa sa itaas, ngunit uulitin ko itong muli: ang throw keyword. Halimbawa ng manu-manong paghahagis ng exception:
throw new NullPointerException();

107. Maaari bang magtapon ng exception ang pangunahing paraan? Kung gayon, kung gayon saan ito pupunta?

Una sa lahat, nais kong tandaan na ang pangunahing pamamaraan ay hindi hihigit sa isang ordinaryong pamamaraan. Oo, ito ay tinatawag ng virtual machine upang simulan ang pagpapatupad ng isang programa, ngunit higit pa doon, maaari itong tawagan mula sa anumang iba pang code. Nangangahulugan iyon na napapailalim din ito sa karaniwang mga panuntunan tungkol sa pagpahiwatig ng mga naka-check na pagbubukod pagkatapos ng mga throws na keyword:
public static void main(String[] args) throws IOException {
Alinsunod dito, maaari itong magtapon ng mga pagbubukod. Kapag ang pangunahing ay tinawag bilang panimulang punto ng programa (sa halip na sa pamamagitan ng ibang paraan), kung gayon ang anumang pagbubukod na ihahagis nito ay hahawakan ng UncaughtExceptionHandler . Ang bawat thread ay may isang ganoong handler (iyon ay, mayroong isang ganoong handler sa bawat thread). Kung kinakailangan, maaari kang lumikha ng iyong sariling handler at itakda ito sa pamamagitan ng pagtawag sa pampublikong static void main(String[] args) throws IOException {setDefaultUncaughtExceptionHandler method on a public static void main(String[] args) throws IOException {Thread object.

Multithreading

Paggalugad ng mga tanong at sagot mula sa isang job interview para sa isang Java developer position.  Bahagi 12 - 3

108. Anong mga mekanismo para sa pagtatrabaho sa isang multithreaded na kapaligiran ang alam mo?

Ang mga pangunahing mekanismo para sa multithreading sa Java ay:
  • Ang naka-synchronize na keyword, na isang paraan para i-lock ng thread ang isang method/block kapag pumasok ito, na pumipigil sa pagpasok ng ibang mga thread.

  • Tinitiyak ng pabagu-bagong keyword ang pare-parehong pag-access sa isang variable na na-access ng iba't ibang mga thread. Iyon ay, kapag ang modifier na ito ay inilapat sa isang variable, ang lahat ng mga operasyon upang italaga at basahin ang variable na iyon ay magiging atomic. Sa madaling salita, hindi kokopyahin ng mga thread ang variable sa kanilang lokal na memorya at babaguhin ito. Babaguhin nila ang orihinal na halaga nito.

  • Runnable — Maaari naming ipatupad ang interface na ito (na binubuo ng iisang run() method) sa ilang klase:

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

    At sa sandaling lumikha kami ng isang bagay ng klase na iyon, maaari kaming magsimula ng isang bagong thread sa pamamagitan ng pagpasa ng aming object sa Thread constructor at pagkatapos ay tawagan ang start() na paraan:

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

    Ang paraan ng pagsisimula ay nagpapatakbo ng ipinatupad na run() na pamamaraan sa isang hiwalay na thread.

  • Thread — Maari nating mamana ang klase na ito at i-override ang paraan ng pagpapatakbo nito :

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

    Maaari tayong magsimula ng bagong thread sa pamamagitan ng paglikha ng object ng klase na ito at pagkatapos ay tawagan ang start() method:

    new CustomThread().start();

  • Concurrency — Ito ay isang pakete ng mga tool para sa pagtatrabaho sa isang multithreaded na kapaligiran.

    Binubuo ito ng:

    • Mga Kasabay na Koleksyon — Ito ay isang koleksyon ng mga koleksyon na tahasang ginawa para magtrabaho sa isang multithreaded na kapaligiran.

    • Mga Queue — Mga espesyal na pila para sa isang multithreaded na kapaligiran (pagha-block at hindi pagharang).

    • Mga Synchronizer — Ito ay mga espesyal na kagamitan para sa pagtatrabaho sa isang multithreaded na kapaligiran.

    • Mga Tagapagpatupad — Mga mekanismo para sa paglikha ng mga thread pool.

    • Mga Lock — Mga mekanismo ng pag-synchronize ng thread na mas nababaluktot kaysa sa mga karaniwang (naka-synchronize, maghintay, ipaalam, ipaalam sa Lahat).

    • Atomics — Mga klase na na-optimize para sa multithreading. Ang bawat isa sa kanilang mga operasyon ay atomic.

109. Sabihin sa amin ang tungkol sa pag-synchronize sa pagitan ng mga thread. Para saan ang wait(), notify(), notifyAll(), at join() method?

Ang pag-synchronize sa pagitan ng mga thread ay tungkol sa naka-synchronize na keyword. Maaaring ilagay ang modifier na ito nang direkta sa block:
synchronized (Main.class) {
   // Some logic
}
O direkta sa lagda ng pamamaraan:
public synchronized void move() {
   // Some logic }
Tulad ng sinabi ko kanina, ang naka-synchronize ay isang mekanismo para sa pag-lock ng isang bloke/pamamaraan sa iba pang mga thread sa sandaling pumasok ang isang thread. Isipin natin ang isang code block/pamamaraan bilang isang silid. May ilang thread na lumalapit sa silid, pumasok dito, at ni-lock ang pinto gamit ang susi nito. Kapag ang ibang mga thread ay lumalapit sa silid, nakita nilang naka-lock ang pinto at naghihintay sa malapit hanggang sa maging available ang silid. Kapag ang unang thread ay tapos na sa negosyo nito sa silid, binubuksan nito ang pinto, aalis sa silid, at ilalabas ang susi. Ilang beses kong binanggit ang isang susi para sa isang dahilan — dahil mayroon talagang kahalintulad na bagay. Ito ay isang espesyal na bagay na may abala/libreng estado. Ang bawat bagay sa Java ay may ganoong bagay, kaya kapag ginamit namin ang naka-synchronize na bloke, kailangan naming gumamit ng mga panaklong upang ipahiwatig ang bagay na ang mutex ay mai-lock:
Cat cat = new Cat();
synchronized (cat) {
   // Some logic
}
Maaari din tayong gumamit ng mutex na nauugnay sa isang klase, tulad ng ginawa ko sa unang halimbawa ( Main.class ). Pagkatapos ng lahat, kapag gumagamit kami ng naka-synchronize sa isang pamamaraan, hindi namin tinukoy ang bagay na gusto naming i-lock, tama ba? Sa kasong ito, para sa mga non-static na pamamaraan, ang mutex na mai-lock ay ang bagay na ito , ibig sabihin, ang kasalukuyang bagay ng klase. Para sa mga static na pamamaraan, ang mutex na nauugnay sa kasalukuyang klase ( this.getClass(); ) ay naka-lock. wait() ay isang paraan na nagpapalaya sa mutex at inilalagay ang kasalukuyang thread sa waiting state, na parang nakakabit sa kasalukuyang monitor (tulad ng anchor). Dahil dito, ang paraang ito ay matatawag lamang mula sa isang naka-synchronize na bloke o pamamaraan. Kung hindi, ano ang hinihintay nito at ano ang ilalabas?). Tandaan din na ito ay isang paraan ng klase ng Bagay . Well, hindi isa, ngunit tatlo:
  • wait() inilalagay ang kasalukuyang thread sa waiting state hanggang sa tawagin ng isa pang thread ang notify() o notifyAll() method sa object na ito (pag-uusapan natin ang mga paraang ito mamaya).

  • wait(long timeout) inilalagay ang kasalukuyang thread sa waiting state hanggang sa isa pang thread ang tumawag sa notify() o notifyAll() method sa object na ito o ang time interval na tinukoy ng timeout ay mag-expire.

  • maghintay (mahabang timeout, int nanos) ay tulad ng nakaraang paraan, ngunit dito nanos hinahayaan kang tukuyin nanoseconds (isang mas tumpak na timeout).

  • notify() hinahayaan kang gisingin ang isang random na thread na naghihintay sa kasalukuyang synchronization block. Muli, ang pamamaraang ito ay matatawag lamang sa isang naka-synchronize na bloke o pamamaraan (pagkatapos ng lahat, sa ibang mga lugar ay walang magigising).

  • notifyAll() ginigising ang lahat ng mga thread na naghihintay sa kasalukuyang monitor (ginagamit lang din sa isang naka-synchronize na block o paraan).

110. Paano natin ititigil ang isang thread?

Ang unang bagay na sasabihin dito ay kapag ang run() ay tumakbo hanggang sa pagkumpleto, ang thread ay awtomatikong magwawakas. Ngunit kung minsan gusto naming patayin ang isang thread nang mas maaga sa iskedyul, bago gawin ang pamamaraan. Kaya ano ang gagawin natin? Marahil ay magagamit natin ang stop() na paraan sa Thread object? Hindi! Hindi na ginagamit ang paraang iyon at maaaring magdulot ng mga pag-crash ng system. Paggalugad ng mga tanong at sagot mula sa isang job interview para sa isang Java developer position.  Bahagi 12 - 4Well, ano kung gayon? Mayroong dalawang paraan upang gawin ito: Una , gamitin ang panloob na boolean flag nito. Tingnan natin ang isang halimbawa. Mayroon kaming pagpapatupad ng isang thread na dapat magpakita ng isang partikular na parirala sa screen hanggang sa ganap na tumigil ang thread:
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;
   }
}
Ang pagtawag sa stopRunningThread() na pamamaraan ay nagtatakda ng panloob na bandila sa false, na nagiging sanhi ng run() na paraan upang wakasan. Tawagan natin ito sa pangunahing :
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...");
Bilang resulta, makakakita tayo ng ganito sa console:
Nagsisimula ang program... Ang thread ay nagpapatupad ng ilang logic... Ang thread ay nagpapatupad ng ilang logic... Ang thread ay nagpapatupad ng ilang logic... Ang thread ay nagpapatupad ng ilang logic... Ang thread ay nagpapatupad ng ilang logic... Ang thread ay nagpapatupad ng ilang lohika... Huminto ang programa... Huminto ang thread!
Nangangahulugan iyon na nagsimula ang aming thread, nag-print ng ilang mensahe sa console, at pagkatapos ay matagumpay na tumigil. Tandaan na ang bilang ng mga mensaheng ipinapakita ay mag-iiba mula sa paglulunsad hanggang sa paglulunsad. At kung minsan ang auxiliary thread ay maaaring hindi magpakita ng kahit ano. Ang partikular na pag-uugali ay depende sa kung gaano katagal natutulog ang pangunahing thread. Kapag mas matagal itong natutulog, mas maliit ang posibilidad na ang auxiliary thread ay hindi makapagpapakita ng kahit ano. Sa oras ng pagtulog na 1 ms, halos hindi mo na makikita ang mga mensahe. Ngunit kung itinakda mo ito sa 20 ms, halos palaging ipinapakita ang mga mensahe. Kapag ang oras ng pagtulog ay maikli, ang thread ay walang oras upang magsimula at gawin ang gawain nito. Sa halip, agad itong napatigil. Ang pangalawang paraan ay ang paggamit ng interrupted() na paraan sa Thread object. Ibinabalik nito ang halaga ng internal interrupted flag, na false bilang default. O ang interrupt() na pamamaraan nito, na nagtatakda sa flag na ito sa true (kapag true ang flag , dapat tumigil sa pagtakbo ang thread). Tingnan natin ang isang halimbawa:
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!");
       }
   }
}
Tumatakbo sa pangunahing :
System.out.println("Program starting...");
Thread thread = new CustomThread();
thread.start();
Thread.sleep(3);
thread.interrupt();
System.out.println("Program stopping...");
Ang resulta ng pagpapatakbo nito ay kapareho ng sa unang kaso, ngunit mas gusto ko ang diskarteng ito: nagsulat kami ng mas kaunting code at gumamit ng mas handa, karaniwang pag-andar. Well, iyon lang para sa araw na ito!
Mga komento
  • Sikat
  • Bago
  • Luma
Dapat kang naka-sign in upang mag-iwan ng komento
Wala pang komento ang page na ito