JavaRush /Java Blog /Random-TL /Pagsusuri ng mga tanong at sagot mula sa mga panayam para...

Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java. Bahagi 12

Nai-publish sa grupo
Kamusta! Kaalaman ay kapangyarihan. Ang mas maraming kaalaman na mayroon ka bago ang iyong unang pakikipanayam, mas tiwala ang mararamdaman mo dito. Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 1Sa isang mahusay na dami ng kaalaman, mahihirapan kang malito, at sa parehong oras, magagawa mong sorpresahin ang iyong tagapanayam. Samakatuwid, ngayon, nang walang karagdagang ado, patuloy naming palalakasin ang iyong theoretical base sa pamamagitan ng pagsusuri sa 250+ na tanong para sa isang developer ng Java . Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 2

103. Ano ang mga patakaran para sa pagsuri sa mga eksepsiyon sa mana?

Kung naiintindihan ko nang tama ang tanong, nagtatanong sila tungkol sa mga patakaran para sa pagtatrabaho nang may mga pagbubukod sa panahon ng pagmamana, at ang mga ito ay ang mga sumusunod:
  • Ang isang na-override o ipinatupad na paraan sa isang descendant/implementation ay hindi makakapagtapon ng mga naka-check na exception na mas mataas sa hierarchy kaysa sa mga exception sa superclass/interface na paraan.
Iyon ay, kung mayroon kaming isang tiyak na interface ng Hayop na may isang pamamaraan na nagtatapon ng IOException :
public  interface Animal {
   void voice() throws IOException;
}
Sa pagpapatupad ng interface na ito, hindi kami maaaring magtapon ng mas pangkalahatang itinapon na exception (halimbawa, Exception , Throwable ), ngunit maaari naming palitan ito ng descendant exception, tulad ng FileNotFoundException :
public class Cat implements Animal {
   @Override
   public void voice() throws FileNotFoundException {
// некоторая реализация
   }
}
  • Dapat isama ng subclass constructor sa mga throws nito ang lahat ng exception classes na itinapon ng superclass constructor na tinatawag kapag ginawa ang object.
Ipagpalagay na ang constructor ng klase ng Animal ay nagtatapon ng maraming mga pagbubukod:
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Pagkatapos ay dapat ding ipahiwatig ng tagapagmana ng klase ang mga ito sa constructor:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
O, tulad ng sa kaso ng mga pamamaraan, maaari mong tukuyin hindi ang parehong mga pagbubukod, ngunit mas pangkalahatan. Sa aming kaso, ito ay sapat na upang tukuyin ang isang mas pangkalahatang pagbubukod - Exception , dahil ito ang karaniwang ninuno ng lahat ng tatlong mga pagbubukod na isinasaalang-alang:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Maaari ka bang sumulat ng code para sa kung kailan hindi maisasakatuparan ang panghuling bloke?

Una, tandaan natin kung ano ang wakas . Noong nakaraan, tiningnan namin ang mekanismo para sa paghuli ng mga exception: ang try block ay nagbabalangkas sa catching area, habang ang catch block (mga) ay ang code na gagana kapag may itinapon na partikular na exception. Panghuli ay ang pangatlong bloke ng code pagkatapos na sa wakas ay mapapalitan ng catch ngunit hindi eksklusibo sa isa't isa. Ang kakanyahan ng bloke na ito ay palaging gumagana ang code sa loob nito, anuman ang resulta ng pagsubok o paghuli (hindi alintana kung ang isang pagbubukod ay itinapon o hindi). Ang mga kaso ng pagkabigo nito ay napakabihirang at sila ay abnormal. Ang pinakasimpleng kaso ng pagkabigo ay kapag ang System.exit(0) na pamamaraan ay tinawag sa code sa itaas , na nagtatapos sa programa (pinapatay ito):
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("Данное сообщение не будет выведенно в консоль");
}
Mayroon ding ilang iba pang mga sitwasyon kung saan sa wakas ay hindi gagana:
  • Abnormal na pagwawakas ng program na dulot ng mga kritikal na problema sa system, o ang pagbagsak ng ilang Error na "mag-crash" sa application (isang halimbawa ng error ay maaaring ang parehong StackOwerflowError na nangyayari kapag umapaw ang memorya ng stack).
  • Kapag ang deamon thread ay dumaan sa ry...sa wakas ay naharang at kahanay nito ang programa ay nagtatapos. Pagkatapos ng lahat, ang thread ng deamon ay isang thread para sa mga aksyon sa background, iyon ay, ito ay hindi isang priyoridad at sapilitan, at ang application ay hindi maghintay para sa trabaho nito upang matapos.
  • Ang pinakakaraniwang infinite loop, sa try or catch , minsan kung saan ang daloy ay mananatili doon magpakailanman:

    try {
       while (true) {
       }
    } finally {
       System.out.println("Данное сообщение не будет выведенно в консоль");
    }

Ang tanong na ito ay medyo sikat sa mga panayam para sa mga baguhan, kaya ang ilang mga pambihirang sitwasyon ay nagkakahalaga ng pag-alala. Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 3

105. Sumulat ng isang halimbawa ng paghawak ng maraming exception sa isang catch block

1) Marahil ang tanong ay naitanong nang hindi tama. Sa pagkakaintindi ko, ang tanong na ito ay nangangahulugan ng maraming catches para sa isang bloke ng pagsubok :
try {
  throw new FileNotFoundException();
} catch (FileNotFoundException e) {
   System.out.print("Упс, у вас упало исключение - " + e);
} catch (IOException e) {
   System.out.print("Упс, у вас упало исключение - " + e);
} catch (Exception e) {
   System.out.print("Упс, у вас упало исключение - " + e);
}
Kung may naganap na exception sa isang try block , ang mga catch block ay halili na susubukan na saluhin ito mula sa itaas hanggang sa ibaba. Kung ang isang partikular na catch block ay magtagumpay, ito ay magkakaroon ng karapatang pangasiwaan ang exception, habang ang iba pang mga block sa ibaba ay hindi na magiging kayang subukang hulihin ito at iproseso sa sarili nilang paraan. Samakatuwid, ang mas makitid na mga eksepsiyon ay inilalagay nang mas mataas sa catch block chain, at ang mas malawak na mga exception ay inilalagay na mas mababa. Halimbawa, kung sa aming unang catch block ay nahuli ang isang exception ng Exception class , ang mga nasuri na exception ay hindi makakapasok sa mga natitirang block (ang natitirang mga block na may Exception descendants ay ganap na walang silbi). 2) Ang tanong ay naitanong nang tama. Sa kasong ito, ang aming pagproseso ay magiging ganito ang hitsura:
try {
  throw new NullPointerException();
} catch (Exception e) {
   if (e instanceof FileNotFoundException) {
       // некоторая обработка с сужением типа (FileNotFoundException)e
   } else if (e instanceof ArithmeticException) {
       // некоторая обработка с сужением типа (ArithmeticException)e
   } else if(e instanceof NullPointerException) {
       // некоторая обработка с сужением типа (NullPointerException)e
   }
Ang pagkakaroon ng nahuli ng isang exception sa pamamagitan ng catch , sinusubukan naming alamin ang partikular na uri nito sa pamamagitan ng instanceof method , na ginagamit upang suriin kung ang isang bagay ay kabilang sa isang tiyak na uri, upang sa ibang pagkakataon ay maaari naming paliitin ito sa ganitong uri nang walang negatibong kahihinatnan. Ang parehong isinasaalang-alang na mga diskarte ay maaaring gamitin sa parehong sitwasyon, ngunit sinabi ko na ang tanong ay hindi tama dahil hindi ko tatawagin ang pangalawang opsyon na mabuti at hindi ko nakita ito sa aking pagsasanay, habang sa parehong oras ang unang pamamaraan na may multicatches ay nakatanggap ng laganap. pansin, kumakalat. Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 4

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 itaas, ngunit gayunpaman ay uulitin ko ang keyword na ito - throw . Halimbawa ng paggamit (pagpipilit ng pagbubukod):
throw new NullPointerException();

107. Maaari bang ang pangunahing pamamaraan ay magtapon ng isang pagbubukod ng throws? Kung gayon, saan ito ililipat?

Una sa lahat, nais kong tandaan na ang pangunahing ay hindi higit sa isang regular na pamamaraan, at oo, tinawag ito ng virtual machine upang simulan ang pagpapatupad ng programa, ngunit bukod dito, maaari itong tawagan mula sa anumang iba pang code. Iyon ay, napapailalim din ito sa karaniwang mga panuntunan para sa pagtukoy ng mga naka-check na pagbubukod pagkatapos ng mga throw :
public static void main(String[] args) throws IOException {
Alinsunod dito, ang mga pagbubukod ay maaari ding mangyari dito. Kung ang pangunahing ay hindi tinawag sa ilang paraan, ngunit sinimulan bilang isang punto ng paglulunsad ng programa, kung gayon ang pagbubukod na inihagis nito ay hahawakan ng .UncaughtExceptionHandler interceptor . Ang handler na ito ay isa sa bawat thread (iyon ay, isang handler sa bawat thread). Kung kinakailangan, maaari kang lumikha ng iyong sariling handler at itakda ito gamit ang setDefaultUncaughtExceptionHandler method na tinatawag sa Thread object .

Multithreading

Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 5

108. Anong mga tool ang alam mo para sa pagtatrabaho sa multithreading?

Basic/Basic Tools para sa Paggamit ng Multithreading sa Java:
  • Ang naka-synchronize ay isang mekanismo para sa pagsasara (pag-block) ng isang paraan/block kapag ang isang thread ay pumasok dito, mula sa iba pang mga thread.
  • Ang pabagu-bago ng isip ay isang mekanismo para sa pagtiyak ng pare-parehong pag-access sa isang variable ng iba't ibang mga thread, iyon ay, sa pagkakaroon ng modifier na ito sa isang variable, ang lahat ng mga pagpapatakbo ng pagtatalaga at pagbabasa ay dapat na atomic. Sa madaling salita, hindi kokopyahin ng mga thread ang variable na ito sa kanilang lokal na memorya at babaguhin ito, ngunit babaguhin ang orihinal na halaga nito.
Magbasa pa tungkol sa volatile dito .
  • Ang Runnable ay isang interface na maaaring ipatupad (sa partikular, ang paraan ng pagpapatakbo nito) sa isang partikular na klase:
public class CustomRunnable implements Runnable {
   @Override
   public void run() {
       // некоторая логика
   }
}
At sa pagkakaroon ng paglikha ng object ng klase na ito, maaari kang magsimula ng bagong thread sa pamamagitan ng pagtatakda ng object na ito sa constructor ng bagong Thread object at pagtawag nito sa start() method :
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.
  • Ang thread ay isang klase, na nagmana mula sa kung saan (habang ini-override ang run method ):
public class CustomThread extends Thread {
   @Override
   public void run() {
       // некоторая логика
   }
}
At sa pamamagitan ng paglikha ng isang object ng klase na ito at paglulunsad nito gamit ang start() method , sa gayon ay maglulunsad kami ng bagong thread:
new CustomThread().start();
  • Ang Concurrency ay isang package na may mga tool para sa pagtatrabaho sa isang multi-threaded na kapaligiran.
Binubuo ito ng:
  • Concurrent Collections - isang set ng mga koleksyon na dalubhasa para sa pagtatrabaho sa isang multi-threaded na kapaligiran.
  • Mga Queue - mga espesyal na pila para sa isang multi-threaded na kapaligiran (pagha-block at hindi pagharang).
  • Ang mga synchronizer ay mga espesyal na kagamitan para sa pagtatrabaho sa isang multi-threaded na kapaligiran.
  • Ang mga tagapagpatupad ay mga mekanismo para sa paglikha ng mga thread pool.
  • Mga kandado - mga mekanismo ng pag-synchronize ng thread (mas nababaluktot kaysa sa mga karaniwang - naka-synchronize, maghintay, ipaalam, ipaalam sa Lahat).
  • Ang Atomics ay mga klase na na-optimize para sa multi-threaded execution; ang bawat operasyon ay atomic.
Magbasa nang higit pa tungkol sa kasabay na pakete dito .

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

Sa pagkakaintindi ko sa tanong, ang pag-synchronize sa pagitan ng mga thread ay tungkol sa key modifier - synchronized . Maaaring ilagay ang modifier na ito nang direkta sa tabi ng bloke:
synchronized (Main.class) {
   // некоторая логика
}
O direkta sa lagda ng pamamaraan:
public synchronized void move() {
   // некоторая логика}
Tulad ng sinabi ko kanina, ang naka-synchronize ay isang mekanismo na nagbibigay-daan sa iyo upang isara ang isang bloke/pamamaraan mula sa iba pang mga thread kapag napasok na ito ng isang thread. Isipin ang isang bloke/paraan bilang isang silid. Ang ilang batis, pagdating dito, ay papasok dito at i-lock ito, ang ibang mga batis, pagdating sa silid at makitang sarado ito, ay maghihintay malapit dito hanggang sa ito ay libre. Nang magawa ang negosyo nito, ang unang thread ay umalis sa silid at inilabas ang susi. At hindi para sa wala na patuloy kong pinag-uusapan ang susi, dahil talagang umiiral ito. Ito ay isang espesyal na bagay na may abala/libreng estado. Ang bagay na ito ay naka-attach sa bawat Java object, kaya kapag gumagamit ng isang naka-synchronize na bloke kailangan naming ipahiwatig sa panaklong ang bagay na ang mutex ay gusto naming isara ang pinto sa:
Cat cat = new Cat();
synchronized (cat) {
   // некоторая логика
}
Maaari ka ring gumamit ng class mutex, tulad ng ginawa ko sa unang halimbawa ( Main.class ). Kapag gumagamit kami ng naka-synchronize sa isang pamamaraan, hindi namin tinukoy ang bagay na gusto naming isara, tama ba? Sa kasong ito, para sa isang non-static na pamamaraan, isasara nito ang mutex ng object na ito , iyon ay, ang kasalukuyang object ng klase na ito. Ang static ay isasara sa mutex ng kasalukuyang klase ( this.getClass(); ). Maaari kang magbasa ng higit pa tungkol sa mutex dito . Well, basahin ang tungkol sa naka-synchronize dito . Ang Wait() ay isang paraan na naglalabas ng mutex at inilalagay ang kasalukuyang thread sa standby mode, na parang naka-attach sa kasalukuyang monitor (tulad ng anchor). Dahil dito, ang pamamaraang ito ay matatawag lamang mula sa isang naka-synchronize na bloke o pamamaraan (kung hindi man, ano ang dapat na libre at kung ano ang dapat nitong asahan). Tandaan din na ito ay isang paraan ng klase ng Bagay . Mas tiyak, hindi isa, ngunit kahit tatlo:
  • Wait() - inilalagay ang kasalukuyang thread sa wait mode hanggang sa tawagin ng isa pang thread ang notify() o notifyAll() method para sa object na ito (pag-uusapan natin ang mga pamamaraang ito mamaya).

  • Wait (long timeout) - inilalagay ang kasalukuyang thread sa wait mode hanggang sa tawagin ng isa pang thread ang notify() o notifyAll() na paraan sa object na ito o ang tinukoy na timeout ay mag-expire .

  • Maghintay (mahabang timeout, int nanos) - katulad ng nauna, nanos lang ang nagpapahintulot sa iyo na tukuyin ang mga nanosecond (mas tumpak na setting ng oras).

  • Notify() ay isang paraan na nagbibigay-daan sa iyong gisingin ang isang random na thread ng kasalukuyang synchronization block. Muli, maaari lamang itong tawagan sa isang naka-synchronize na bloke o pamamaraan (pagkatapos ng lahat, sa ibang mga lugar ay wala itong sinumang mag-unfreeze).

  • Ang NotifyAll() ay isang paraan na gumigising sa lahat ng naghihintay na mga thread sa kasalukuyang monitor (ginagamit din lamang sa isang naka-synchronize na block o paraan).

110. Paano itigil ang daloy?

Ang unang bagay na sasabihin ay kapag ang run() na pamamaraan ay ganap na naisakatuparan , ang thread ay awtomatikong masisira. Ngunit kung minsan kailangan mong patayin siya nang maaga sa iskedyul, bago makumpleto ang pamamaraang ito. Kaya ano ang dapat nating gawin pagkatapos? Marahil ang bagay na Thread ay dapat magkaroon ng isang stop() na pamamaraan ? Hindi mahalaga kung paano ito ay! Ang pamamaraang ito ay itinuturing na hindi napapanahon at maaaring humantong sa mga pag-crash ng system. Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 6Well, ano kung gayon? Mayroong dalawang paraan upang gawin ito: Ang una ay ang paggamit ng iyong panloob na boolean flag. Tingnan natin ang isang halimbawa. Mayroon kaming sariling pagpapatupad ng isang thread na dapat magpakita ng isang partikular na parirala sa screen hanggang sa ganap itong tumigil:
public class CustomThread extends Thread {
private boolean isActive;

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

   @Override
   public void run() {
       {
           while (isActive) {
               System.out.println("Поток выполняет некую логику...");
           }
           System.out.println("Поток остановлен!");
       }
   }

   public void stopRunningThread() {
       isActive = false;
   }
}
Kapag ginagamit ang stopRunning() method , nagiging false ang internal flag at hihinto sa pagtakbo ang run method . Patakbuhin natin ito sa pangunahing :
System.out.println("Начало выполнения программы");
CustomThread thread = new CustomThread();
thread.start();
Thread.sleep(3);
// пока наш основной поток спит, вспомогательный  CustomThread работает и выводит в коноль своё сообщение
thread.stopRunningThread();
System.out.println("Конец выполнения программы");
Bilang resulta, makakakita tayo ng ganito sa console:
Simula ng pagpapatupad ng programa Ang thread ay nagpapatupad ng ilang lohika... Ang thread ay nagpapatupad ng ilang lohika... Ang thread ay nagpapatupad ng ilang lohika... Ang thread ay nagpapatupad ng ilang lohika... Ang thread ay nagpapatupad ng ilang lohika... Ang thread is executing some logic... End of program execution Huminto ang thread !
Nangangahulugan ito na gumana ang aming thread, naglabas ng isang tiyak na bilang ng mga mensahe sa console at matagumpay na nahinto. Pansinin ko na ang bilang ng mga output ng mensahe ay mag-iiba mula sa run hanggang run; minsan ang karagdagang thread ay hindi naglabas ng kahit ano. Tulad ng napansin ko, depende ito sa oras ng pagtulog ng pangunahing thread, mas mahaba ito, mas kaunting pagkakataon na ang karagdagang thread ay hindi maglalabas ng anuman. Sa oras ng pagtulog na 1ms, ang mga mensahe ay halos hindi na-output, ngunit kung itatakda mo ito sa 20ms, ito ay halos palaging gumagana. Marahil, kapag ang oras ay maikli, ang thread ay walang oras upang simulan at simulan ang trabaho nito, at agad na huminto. Ang pangalawang paraan ay ang paggamit ng interrupted() na paraan sa Thread object, na nagbabalik ng halaga ng internal interrupt na bandila ( false ang flag na ito bilang default ) at ang iba pang interrupt() na pamamaraan nito , na nagtatakda ng flag na ito sa true (kapag ito flag ay totoo ang thread ay dapat na huminto sa trabaho nito) . Tingnan natin ang isang halimbawa:
public class CustomThread extends Thread {

   @Override
   public void run() {
       {
           while (!Thread.interrupted()) {
               System.out.println("Поток выполняет некую логику...");
           }
           System.out.println("Поток остановлен!");
       }
   }
}
Tumakbo sa pangunahing :
System.out.println("Начало выполнения программы");
Thread thread = new CustomThread();
thread.start();
Thread.sleep(3);
thread.interrupt();
System.out.println("Конец выполнения программы");
Ang resulta ng pagpapatupad ay magiging kapareho ng sa unang kaso, ngunit mas gusto ko ang diskarteng ito: mas kaunting code ang isinulat namin at gumagamit ng mas handa, karaniwang pag-andar. Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 7Doon tayo titigil ngayon.Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java.  Bahagi 12 - 8
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION