JavaRush /Java блогу /Random-KY /Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун...
Константин
Деңгээл

Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи. 12-бөлүк

Группада жарыяланган
Салам! Бorм – бул күч. Биринчи интервьюга чейин канчалык көп бorмге ээ болсоңуз, анда сиз ошончолук ишенимдүү болосуз. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-1-бөлүкЖакшы бorм менен сизди чаташтыруу кыйын болот, ошол эле учурда маектешиңизди жагымдуу таң калтыра аласыз. Ошондуктан, бүгүн, андан ары созбостон, биз Java иштеп чыгуучусу үчүн 250+ суроолорду карап чыгуу менен теориялык базаңызды бекемдөөнү улантабыз . Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-2-бөлүк

103. Мурастоодо өзгөчөлүктү текшерүү эрежелери кандай?

Эгерде мен суроону туура түшүнсөм, алар мурастоо учурунда өзгөчөлүктөр менен иштөө эрежелери жөнүндө сурап жатышат жана алар төмөнкүдөй:
  • Тукумда/ишке ашырууда жокко чыгарылган же ишке ашырылган ыкма иерархияда суперкласс/интерфейс методундагы өзгөчөлүктөргө караганда жогору турган текшерилген өзгөчөлүктөрдү ыргыта алbyte.
Башкача айтканда, бизде IOException ыргыткан метод менен белгилүү бир Animal интерфейси бар болсо :
public  interface Animal {
   void voice() throws IOException;
}
Бул интерфейсти ишке ашырууда биз жалпы ыргытылган өзгөчөлүктү ыргыта албайбыз (мисалы, Exception , Throwable ), бирок биз аны FileNotFoundException сыяктуу урпак өзгөчөлүгү менен алмаштыра алабыз :
public class Cat implements Animal {
   @Override
   public void voice() throws FileNotFoundException {
// некоторая реализация
   }
}
  • Субкласс конструктору an objectти түзүүдө чакырылган суперкласстын конструктору тарабынан ыргытылган бардык өзгөчө класстарды ыргытуу блокторуна камтышы керек.
Animal классынын конструктору көптөгөн өзгөчөлүктөрдү ыргытат дейли :
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Андан кийин класстын мураскору аларды конструктордо да көрсөтүшү керек:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
Же болбосо, методдордогудай эле, ошол эле өзгөчөлүктөрдү эмес, жалпыларды белгилей аласыз. Биздин учурда, бир кыйла жалпы өзгөчөлүктү көрсөтүү жетиштүү болот - Exception , анткени бул бардык үч өзгөчөлүктүн жалпы түпкү атасы болуп саналат:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Finally блогу аткарылбай турган учурдун codeун жаза аласызбы?

Биринчиден, акыры эмне экенин эстеп көрөлү . Мурда биз өзгөчө учурларды кармоо механизмин карап чыктык: try блогу кармоо аймагын көрсөтөт, ал эми кармоо блогу(лар) белгилүү бир өзгөчөлүк ыргытылганда иштей турган code. Акыр-аягы, үчүнчү code блогу болуп саналат, акыры , аны кармаш менен алмаштырса болот , бирок бири-бирин жокко чыгарbyte. Бул блоктун маңызы, андагы code ар дайым аракеттин же кармоонун натыйжасына карабастан иштейт (өзгөчө учур ыргытылганбы же жокпу). Анын иштебей калган учурлары өтө сейрек кездешет жана алар анормалдуу. Жогорудагы codeдо System.exit (0) ыкмасы чакырылып , программаны токтотот (аны өчүрөт):
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("Данное сообщение не будет выведенно в консоль");
}
Акыры иштебей турган башка жагдайлар да бар :
  • Тутумдун критикалык көйгөйлөрүнөн келип чыккан программанын анормалдуу токтотулушу же тиркемени "буза турган" кандайдыр бир Катанын кулашы (катанын мисалы стек эстутуму толуп кеткенде пайда болгон ошол эле StackOwerflowError болушу мүмкүн).
  • Димон жип ry аркылуу өткөндө ... акыры блокто жана ушуну менен параллелдүү программа аяктайт. Анткени, деамон жип - бул фондо аракеттер үчүн жип, башкача айтканда, бул приоритеттүү жана милдеттүү эмес жана тиркеме өз ишин бүтүргөнчө күтпөйт.
  • try or catch ичиндеги эң кеңири таралган чексиз цикл , анда агым ошол жерде түбөлүк кала берет:

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

Бул суроо жаңы баштагандар үчүн интервьюларда абдан популярдуу, ошондуктан бул өзгөчө кырдаалдардын бир нечесин эстен чыгарбоо керек. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-3-бөлүк

105. Бир кармоо блогунда бир нече өзгөчөлүктү иштетүүгө мисал жазыңыз

1) Балким суроо туура эмес берилгендир. Мен түшүнгөнүм боюнча, бул суроо бир аракет блогу үчүн бир нече кармоону билдирет :
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);
}
Эгерде try блогунда өзгөчө кырдаал пайда болсо , анда catch блоктору кезектешип аны жогорудан ылдыйга карай кармаганга аракет кылышат.Эгер белгилүү бир catch блогу ийгorктүү болсо, ал өзгөчө кырдаалды башкаруу укугун алат, ал эми төмөнкү блоктордун калгандары мындан ары болбой калат. аны кармап, аны өз жолу менен иштетүүгө аракет кыла алышат. Ошондуктан, тар өзгөчөлүктөр кармоо блок чынжырында жогору жайгаштырылат , ал эми кененирээк өзгөчөлүктөр төмөн жайгаштырылат. Мисалы, биздин биринчи catch блогубузда Exception классынын өзгөчө учуру кармалса , анда текшерилген өзгөчөлүктөр калган блокторго кире алbyte ( Exception тукумдары менен калган блоктор таптакыр пайдасыз болот). 2) Суроо туура берилген.Бул учурда биздин иштетүү төмөнкүдөй болот:
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
   }
catch аркылуу өзгөчөлүктү кармап , биз an objectтин белгилүү бир түргө таандык экендигин текшерүү үчүн колдонулган instanceof ыкмасы аркылуу анын конкреттүү түрүн табууга аракет кылабыз , ошондуктан кийинчерээк аны терс кесепеттерсиз ушул түргө чейин кыскарта алабыз. Каралып жаткан эки ыкманы тең бирдей жагдайда колдонсо болот, бирок мен суроо туура эмес деп айттым, анткени мен экинчи вариантты жакшы деп атабайм жана аны өзүмдүн практикамда эч качан көргөн эмесмин, ошол эле учурда көп кармалуу менен биринчи ыкма кеңири таралган. көңүл буруу. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-4-бөлүк

106. Кайсы оператор өзгөчө учурду ыргытууга мажбурлоого мүмкүндүк берет? Мисал жаз

Мен аны жогоруда бир нече жолу колдонгом, бирок ошентсе да мен бул ачкыч сөздү кайталайм - throw . Мисал колдонуу (өзгөчө учурду мажбурлоо):
throw new NullPointerException();

107. Негизги ыкма ыргытуудан өзгөчөлүктү таштай алабы? Андай болсо, кайда которулат?

Биринчиден, мен белгилеп кетким келет, негизги бул кадимки ыкмадан башка эч нерсе эмес, ооба, ал программаны аткарууну баштоо үчүн виртуалдык машина тарабынан чакырылат, бирок мындан тышкары, аны каалаган башка codeдон чакырса болот. Башкача айтканда, ал ыргытуудан кийин текшерилген өзгөчөлүктөрдү көрсөтүү үчүн кадимки эрежелерге баш ийет :
public static void main(String[] args) throws IOException {
Ошого ылайык, анда өзгөчө учурлар да болушу мүмкүн. Эгерде main кандайдыр бир ыкма менен чакырылбай, бирок программаны ишке киргизүү чекити катары башталган болсо, анда ал тарабынан чыгарылган өзгөчөлүктү .UncaughtExceptionHandler интерцептору иштетет . Бул иштеткич ар бир жипте бирден (башкача айтканда, ар бир жипте бир иштеткич). Керек болсо, өзүңүздүн иштеткичиңизди түзүп, аны Thread an objectинде чакырылган setDefaultUncaughtExceptionHandler ыкмасын колдонуп орното аласыз .

Multithreading

Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-5-бөлүк

108. Көп агым менен иштөөнүн кандай куралдарын билесиз?

Javaда Multithreadingди колдонуу үчүн негизги/негизги куралдар:
  • Синхрондоштуруу - бул башка жиптерден жип киргенде ыкманы/блокту жабуу (бөгөттөө) механизми.
  • Учуучу - бул өзгөрмөгө ар кандай жиптер боюнча ырааттуу кирүү мүмкүнчүлүгүн камсыз кылуу механизми, башкача айтканда, бул өзгөргүчтүн өзгөрмөдө болушу менен, бардык дайындоо жана окуу операциялары атомдук болушу керек. Башкача айтканда, жиптер бул өзгөрмөнү жергorктүү эс тутумуна көчүрүп, аны өзгөртпөйт, бирок анын баштапкы маанисин өзгөртөт.
Бул жерде туруксуз жөнүндө көбүрөөк оку .
  • Runnable - бул белгилүү бир класста ишке ашырыла турган интерфейс (айрыкча, анын иштетүү ыкмасы):
public class CustomRunnable implements Runnable {
   @Override
   public void run() {
       // некоторая логика
   }
}
Жана бул класстын an objectисин түзүп, сиз бул an objectти жаңы Thread an objectинин конструкторуна коюп, анын start() ыкмасын чакырып, жаңы жипти баштасаңыз болот :
Runnable runnable = new CustomRunnable();
new Thread(runnable).start();
Start методу ишке ашырылган run() ыкмасын өзүнчө жипте иштетет .
  • Thread - бул класс, андан тукум кууп өткөн ( иштөө ыкмасын жокко чыгарып жатканда ):
public class CustomThread extends Thread {
   @Override
   public void run() {
       // некоторая логика
   }
}
Жана бул класстын an objectин түзүү жана аны start() ыкмасын колдонуу менен ишке киргизүү менен , биз ошону менен жаңы жипти ишке киргизебиз:
new CustomThread().start();
  • Concurrency - бул көп жиптүү чөйрөдө иштөө үчүн куралдары бар пакет.
Ал төмөнкүлөрдөн турат:
  • Concurrent Collections - көп жиптүү чөйрөдө иштөө үчүн адистештирилген коллекциялардын жыйындысы.
  • Кезектер – көп жиптүү чөйрө үчүн адистештирилген кезектер (бөгөттөөчү жана бөгөттөөчү эмес).
  • Синхронизаторлор - көп агымдуу чөйрөдө иштөө үчүн атайын утorталар.
  • Аткаруучулар жип бассейндерин түзүү механизмдери болуп саналат.
  • Кулпулар - жипти синхрондоштуруу механизмдери (стандарттыктарга караганда ийкемдүү - синхрондоштуруу, күтүү, кабарлоо, notifyAll).
  • Атомикалык класстар көп жиптүү аткаруу үчүн оптималдаштырылган; ар бир операция атомдук болуп саналат.
Бул жерде бир эле учурда топтом тууралуу көбүрөөк окуңуз .

109. Жиптердин ортосундагы синхронизация жөнүндө айт. wait(), notify() - notifyAll() join() ыкмалары эмне үчүн колдонулат?

Мен суроону түшүнгөндөй, жиптер ортосундагы синхрондоштуруу негизги өзгөрткүч жөнүндө - синхрондуу . Бул модификатор түз эле блоктун жанына жайгаштырылышы мүмкүн:
synchronized (Main.class) {
   // некоторая логика
}
Же түздөн-түз ыкма колунда:
public synchronized void move() {
   // некоторая логика}
Мен жогоруда айткандай, синхрондоштуруу - бул бир жип ага мурунтан эле киргенде, башка жиптерден блокту/ыкманы жабууга мүмкүндүк берүүчү механизм. Бөлмө катары блокту/ыкманы ойлонуңуз. Кайсы бир агым ага келип, ага кирип, аны бекитет, башка агымдар бөлмөгө келип, анын жабык экенин көрүп, бош болгонго чейин жанында күтүшөт. Өз ишин бүтүргөндөн кийин, биринчи жип бөлмөдөн чыгып, ачкычты коё берет. Ачкыч жөнүндө мен бекеринен айткан эмесмин, анткени ал чындап эле бар. Бул бош/эркин абалга ээ болгон өзгөчө an object. Бул an object ар бир Java an objectисине тиркелет, ошондуктан синхрондоштурулган блокту колдонууда биз кашаанын ичинде мутексин жабууну каалаган an objectти көрсөтүүбүз керек:
Cat cat = new Cat();
synchronized (cat) {
   // некоторая логика
}
Сиз ошондой эле класстын мутексин колдоно аласыз, мен биринчи мисалдагыдай ( Main.class ). Метод боюнча синхрондоштурууну колдонгондо , биз жабууну каалаган an objectти көрсөтпөйбүз, туурабы? Бул учурда, статикалык эмес метод үчүн, ал бул an objectтин мутексине , башкача айтканда, ушул класстын учурдагы an objectисине жабылат. Статикалык класс учурдагы класстын мутексинде жабылат ( this.getClass(); ). Мутекс тууралуу кененирээк бул жерден окуй аласыз . Ооба, бул жерде синхрондоштуруу жөнүндө оку . Wait() - бул мутексти бошотуучу жана учурдагы жипти учурдагы мониторго тиркелген сыяктуу күтүү режимине киргизген ыкма (казык сыяктуу бир нерсе). Ушундан улам, бул ыкманы синхрондоштурулган блоктон же ыкмадан гана чакырса болот (антпесе, ал эмнени боштонду жана эмнени күтүшү керек). Ошондой эле бул Object классынын ыкмасы экенин эске алыңыз . Тагыраак айтканда, бир эмес, үчөө:
  • Wait() - башка жип бул an object үчүн notify() же notifyAll() ыкмасын чакырмайынча учурдагы жипти күтүү режимине коет (бул ыкмалар жөнүндө кийинчерээк сүйлөшөбүз).

  • Күтүү (узак күтүү) - башка жип бул an objectте notify() же notifyAll() ыкмасын чакырмайынча же көрсөтүлгөн таймауттун мөөнөтү бүткүчө учурдагы жипти күтүү режимине коет .

  • Күтө туруңуз (узак убакыт, int nanos) - мурункуга окшош, нанос гана наносекундтарды көрсөтүүгө мүмкүндүк берет (убакыттын так жөндөөсү).

  • Notify() - учурдагы синхрондоштуруу блогунун бир кокустук жипти ойготууга мүмкүндүк берген ыкма. Дагы бир жолу, аны синхрондоштурулган блокто же ыкмада гана чакырса болот (анткени, башка жерлерде аны бошоткон эч ким болбойт).

  • NotifyAll() - учурдагы монитордогу бардык күтүүчү жиптерди ойгото турган ыкма (ошондой эле синхрондоштурулган блокто же ыкмада гана колдонулат).

110. Агымды кантип токтотуу керек?

Биринчи айта турган нерсе, run() ыкмасы толугу менен аткарылганда , жип автоматтык түрдө жок кылынат. Бирок кээде бул ыкма аяктаганга чейин, аны мөөнөтүнөн мурда өлтүрүш керек. Анда эмне кылышыбыз керек? Балким, Thread an objectисинде stop() ыкмасы болушу керектир ? Кандай болбосун! Бул ыкма эскирген деп эсептелет жана системанын бузулушуна алып келиши мүмкүн. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-6-бөлүкАнда эмне болот? Муну жасоонун эки жолу бар: Биринчиси , ички логикалык желекти колдонуу. Келгиле, бир мисал карап көрөлү. Бизде жипти өз алдынча ишке ашыруу бар, ал толугу менен токтогонго чейин экранда белгилүү бир фразаны көрсөтүү керек:
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;
   }
}
stopRunning() ыкмасын колдонгондо , ички желек жалган болуп, иштетүү ыкмасы иштебей калат. Келгиле, аны негизги иштетели :
System.out.println("Начало выполнения программы");
CustomThread thread = new CustomThread();
thread.start();
Thread.sleep(3);
// пока наш основной поток спит, вспомогательный  CustomThread работает и выводит в коноль своё сообщение
thread.stopRunningThread();
System.out.println("Конец выполнения программы");
Натыйжада, биз консолдо ушул сыяктуу нерсени көрөбүз:
Программанын аткарылышынын башталышы Жип кандайдыр бир логиканы аткарып жатат... Жип кандайдыр бир логиканы аткарып жатат... Жип кандайдыр бир логиканы аткарып жатат... Жип кандайдыр бир логиканы аткарып жатат... Жип кандайдыр бир логиканы аткарып жатат... жип кандайдыр бир логиканы аткарып жатат... Программанын аткарылышынын соңу Жип токтотулду!
Бул биздин жип иштеп, консолго белгилүү сандагы билдирүүлөрдү чыгарып, ийгorктүү токтотулганын билдирет. Чыгарылган билдирүүлөрдүн саны ишке жараша өзгөрүп турганын белгилейм; кээде кошумча жип эч нерсе чыгарган эмес. Мен байкагандай, бул негизги жиптин уктоо убактысына жараша болот, ал канчалык узак болсо, кошумча жиптен эч нерсе чыкпоо мүмкүнчүлүгү ошончолук азыраак. Уктоо убактысы 1 мс болсо, билдирүүлөр дээрлик эч качан чыгарылbyte, бирок аны 20 мс кылып койсоңуз, ал дээрлик дайыма иштейт. Балким, убакыт аз болгондо, жип жөн эле баштоого жана ишин баштоого үлгүрбөй, дароо токтоп калат. Экинчи жол - Thread an objectисинде interrupted() ыкмасын колдонуу , ал ички үзүлүү желекчесинин маанисин кайтарат (бул желек демейки боюнча false ) жана анын башка interrupt() ыкмасы , бул желекти чындыкка коет (бул болгондо желек чын , жип өз ишин токтотушу керек) . Келгиле, бир мисал карап көрөлү:
public class CustomThread extends Thread {

   @Override
   public void run() {
       {
           while (!Thread.interrupted()) {
               System.out.println("Поток выполняет некую логику...");
           }
           System.out.println("Поток остановлен!");
       }
   }
}
Негизгиде иштетүү :
System.out.println("Начало выполнения программы");
Thread thread = new CustomThread();
thread.start();
Thread.sleep(3);
thread.interrupt();
System.out.println("Конец выполнения программы");
Аткаруу натыйжасы биринчи учурдагыдай болот, бирок мага бул ыкма жакшыраак жагат: биз азыраак code жазып, даяр, стандарттуу функцияларды көбүрөөк колдонобуз. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-7-бөлүкМына бүгүн биз токтойбуз.Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  12-8-бөлүк
Сериядагы башка материалдар:
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION