JavaRush /Java блогы /Random-KK /Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары. ...
Roman Beekeeper
Деңгей

Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары. 3-бөлім

Топта жарияланған
Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары. 1 бөлім Java негізгі 50 сұхбат сұрақтары мен жауаптары. 2-бөлім

Көп ағынды

37. Java тілінде жаңа ағын (ағын) қалай жасалады?

Қалай болғанда да, құру Thread сыныбын пайдалану арқылы жүзеге асады. Бірақ мұнда нұсқалар болуы мүмкін ...
  1. -ден мұра аламызjava.lang.Thread
  2. java.lang.RunnableБіз an objectісі конструктор Threadкласын қабылдайтын интерфейсті жүзеге асырамыз
Олардың әрқайсысына тоқталайық.

Біз Thread сыныбынан мұра аламыз

Бұл жұмысты орындау үшін, біздің сыныпта біз мұрагерлікке ие боламыз java.lang.Thread. Оның құрамында мет бар run(), бұл бізге қажет нәрсе. Жаңа жіптің барлық өмірі мен логикасы осы әдісте болады. Бұл mainжаңа ағынға арналған әдістің бір түрі. Осыдан кейін біздің сыныптың an objectісін жасау және әдісті орындау ғана қалады start(), ол жаңа ағынды жасайды және онда жазылған логиканы іске қосады. Қарап көрейік:
/**
* Пример того, How создавать треды путем наследования {@link Thread} класса.
*/
class ThreadInheritance extends Thread {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance threadInheritance1 = new ThreadInheritance();
       ThreadInheritance threadInheritance2 = new ThreadInheritance();
       ThreadInheritance threadInheritance3 = new ThreadInheritance();
       threadInheritance1.start();
       threadInheritance2.start();
       threadInheritance3.start();
   }
}
Консольге шығу келесідей болады:

Thread-1
Thread-0
Thread-2
Яғни, мұнда да ағындар кезекпен емес, JVM шешкеніндей орындалатынын көреміз)

Runnable интерфейсін енгізу

Егер сіз мұраға қарсы болсаңыз және/немесе басқа сыныптардың біреуін мұрагер болсаңыз, java.lang.Runnable. Міне, біздің сыныпта біз осы интерфейсті жүзеге асырып, run()осы мысалдағыдай әдісті орындаймыз. Сізге тек көбірек нысандар жасау керек Thread. Көбірек сызықтар нашаррақ болып көрінеді. Бірақ біз тұқым қуалаудың қаншалықты зиянды екенін және одан аулақ болған дұрыс екенін білеміз;) Қарап көрейік:
/**
* Пример того, How создавать треды из интерфейса {@link Runnable}.
* Здесь проще простого - реализуем этот интерфейс и потом передаем в конструктор
* экземпляр реализуемого an object.
*/
class ThreadInheritance implements Runnable {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance runnable1 = new ThreadInheritance();
       ThreadInheritance runnable2 = new ThreadInheritance();
       ThreadInheritance runnable3 = new ThreadInheritance();

       Thread threadRunnable1 = new Thread(runnable1);
       Thread threadRunnable2 = new Thread(runnable2);
       Thread threadRunnable3 = new Thread(runnable3);

       threadRunnable1.start();
       threadRunnable2.start();
       threadRunnable3.start();
   }
}
Ал орындалу нәтижесі:

Thread-0
Thread-1
Thread-2

38. Процесс пен жіптің айырмашылығы неде?

Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары.  3 - 1 бөлімПроцесс пен ағынның арасында келесі айырмашылықтар бар:
  1. Орындалып жатқан бағдарлама процесс деп аталады, ал Thread - процестің ішкі жиыны.
  2. Процестер тәуелсіз, ал ағындар процестің ішкі жиыны болып табылады.
  3. Процестер жадта әртүрлі addressтік кеңістікке ие, ал ағындар жалпы мекенжай кеңістігін қамтиды.
  4. Мәтінмәнді ауыстыру процестермен салыстырғанда ағындар арасында жылдамырақ.
  5. Процессаралық байланыс ағындар аралық байланысқа қарағанда баяу және қымбатырақ.
  6. Негізгі процестегі кез келген өзгерістер еншілес процеске әсер етпейді, ал негізгі ағындағы өзгерістер еншілес ағынға әсер етуі мүмкін.

39. Көп ағындылықтың қандай артықшылықтары бар?

Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары.  3 - 2 бөлім
  1. Көп ағынды қолдану қолданбаға/бағдарламаға кейбір фондық тапсырмаларды орындап тұрса да әрқашан енгізуге жауап беруге мүмкіндік береді;
  2. Көп ағынды ағындар дербес орындалатындықтан, тапсырмаларды тезірек орындауға мүмкіндік береді;
  3. Multithreading кэшті жақсы пайдалануды қамтамасыз етеді, себебі ағындар жалпы жад ресурстарын бөліседі;
  4. Бір server бірнеше ағындарды бір уақытта іске қоса алатындықтан, көп ағынды serverдің қажетті көлемін азайтады.

40. Жіптің өмірлік цикліндегі күйлер қандай?

Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары.  3 - 3 бөлім
  1. Жаңа: Бұл күйде сынып нысаны Threadnew операторы арқылы жасалады, бірақ ағын жоқ. Біз шақырмайынша жіп басталмайды start().
  2. Орындалатын: Бұл күйде ағын әдісті шақырғаннан кейін іске қосуға дайын бастау(). Дегенмен, оны ағынды жоспарлаушы әлі таңдаған жоқ.
  3. Орындалуда: бұл күйде ағынды жоспарлаушы дайын күйден ағынды таңдайды және ол іске қосылады.
  4. Күту/бұғаттау: бұл күйде ағын жұмыс істемейді, бірақ әлі тірі немесе басқа ағынның аяқталуын күтуде.
  5. Өлі/тоқтатылды: әдіс шыққанда, run()ағын тоқтатылған немесе өлі күйде болады.

41. Жіпті екі рет бастауға бола ма?

Жоқ, біз ағынды қайта іске қоса алмаймыз, себебі ағын іске қосылғаннан кейін және орындалғаннан кейін ол Өлі күйге өтеді. Сондықтан ағынды екі рет іске қосуға тырыссақ, ол runtimeException " java.lang.IllegalThreadStateException " шығарады. Қарап көрейік:
class DoubleStartThreadExample extends Thread {

   /**
    * Имитируем работу треда
    */
   public void run() {
	// что-то происходит. Для нас не существенно на этом этапе
   }

   /**
    * Запускаем тред дважды
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
Жұмыс сол ағынның екінші басына жеткенде, ерекшелік болады. Өзіңіз көріңіз;) жүз рет естігенше, бір рет көрген жақсы.

42. start() әдісін шақырмай, тікелей run() әдісін шақырсаңыз ше?

Иә, run()әрине әдісті шақыруға болады, бірақ бұл жаңа ағынды жасамайды және оны бөлек ағын ретінде орындамайды. Бұл жағдайда қарапайым әдісті шақыратын қарапайым нысан. Егер біз әдіс туралы айтатын болсақ start(), онда бұл басқа мәселе. Бұл әдісті іске қосу арқылы runtimeол жаңасын іске қосады және ол өз кезегінде біздің әдісті іске қосады;) Маған сенбесеңіз, көріңіз:
class ThreadCallRunExample extends Thread {

   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.print(i);
       }
   }

   public static void main(String args[]) {
       ThreadCallRunExample runExample1 = new ThreadCallRunExample();
       ThreadCallRunExample runExample2 = new ThreadCallRunExample();

       // просто будут вызваны в потоке main два метода, один за другим.
       runExample1.run();
       runExample2.run();
   }
}
Ал консольге шығу келесідей болады:

0123401234
Жіптің жасалмағанын көруге болады. Барлығы кәдімгі сынып сияқты жұмыс істеді. Алдымен бірінші класс әдісі жұмыс істеді, содан кейін екіншісі.

43. Демон ағыны дегеніміз не?

Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары.  3 - 4 бөлімДемон ағыны (бұдан әрі - демон ағыны) - басқа ағынға қатысты фондық режимде тапсырмаларды орындайтын ағын. Яғни, оның жұмысы тек басқа (негізгі) жіппен бірге орындалуы қажет көмекші тапсырмаларды орындау болып табылады. Автоматты түрде жұмыс істейтін көптеген демон ағындары бар, мысалы, қоқыс жинағыш, аяқтаушы және т.б.

Неліктен Java демон ағынын жабады?

Демон ағынының жалғыз мақсаты - ол фондық қолдау тапсырмасы үшін пайдаланушы ағынына қызметтерді қамтамасыз етеді. Сондықтан, егер негізгі ағын аяқталса, жұмыс уақыты оның барлық демон ағындарын автоматты түрде жабады.

Thread сыныбында жұмыс істеу әдістері

Сынып java.lang.Threadжіп демонымен жұмыс істеудің екі әдісін ұсынады:
  1. public void setDaemon(boolean status)- бұл демон ағыны болатынын көрсетеді. Әдепкі мән false- бұл бөлек көрсетілмесе демон емес ағындар жасалатынын білдіреді.
  2. public boolean isDaemon()daemon- шын мәнінде бұл алдыңғы әдісті пайдаланып орнатқан айнымалы үшін гетер .
Мысалы:
class DaemonThreadExample extends Thread {

   public void run() {
       // Проверяет, демон ли этот поток or нет
       if (Thread.currentThread().isDaemon()) {
           System.out.println("daemon thread");
       } else {
           System.out.println("user thread");
       }
   }

   public static void main(String[] args) {
       DaemonThreadExample thread1 = new DaemonThreadExample();
       DaemonThreadExample thread2 = new DaemonThreadExample();
       DaemonThreadExample thread3 = new DaemonThreadExample();

       // теперь thread1 - поток-демон.
       thread1.setDaemon(true);

       System.out.println("демон?.. " + thread1.isDaemon());
       System.out.println("демон?.. " + thread2.isDaemon());
       System.out.println("демон?.. " + thread3.isDaemon());

       thread1.start();
       thread2.start();
       thread3.start();
   }
}
Консоль шығысы:

демон?.. true
демон?.. false
демон?.. false
daemon thread
user thread
user thread
Шығарылымнан біз жіптің өзінде статикалық currentThread()әдісті қолдана отырып, бір жағынан оның қандай жіп екенін анықтай алатынымызды көреміз, екінші жағынан, егер бізде осы жіптің an objectісіне сілтеме болса, біз білуге ​​болады. тікелей одан. Бұл конфигурацияда қажетті икемділікті береді.

44. Жіпті жасағаннан кейін оны демон жасауға болады ма?

Жоқ. Егер сіз мұны жасасаңыз, ол ерекше жағдайды шығарады IllegalThreadStateException. Сондықтан, біз демон ағынын ол басталғанға дейін ғана жасай аламыз. Мысалы:
class SetDaemonAfterStartExample extends Thread {

   public void run() {
       System.out.println("Working...");
   }

   public static void main(String[] args) {
       SetDaemonAfterStartExample afterStartExample = new SetDaemonAfterStartExample();
       afterStartExample.start();

       // здесь будет выброшено исключение
       afterStartExample.setDaemon(true);
   }
}
Консоль шығысы:

Working...
Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.setDaemon(Thread.java:1359)
	at SetDaemonAfterStartExample.main(SetDaemonAfterStartExample.java:14)

45. Өшіру ілмектері дегеніміз не?

Shutdownhook – JVM (Java виртуалды машинасы) өшірілгенге дейін жанама түрде шақырылатын ағын. Сондықтан оны Java виртуалды машинасы қалыпты немесе кенеттен өшкенде ресурсты тазалау немесе күйді сақтау үшін пайдалана аламыз. shutdown hookБіз келесі әдісті қолданып қосуға болады :
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Мысалда көрсетілгендей:
/**
* Программа, которая показывает How запустить shutdown hook тред,
* который выполнится аккурат до окончания работы JVM
*/
class ShutdownHookThreadExample extends Thread {

   public void run() {
       System.out.println("shutdown hook задачу выполнил");
   }

   public static void main(String[] args) {

       Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());

       System.out.println("Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.");
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
Консоль шығысы:

Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.
shutdown hook задачу выполнил

46. ​​Синхрондау дегеніміз не?

Java-дағы синхрондау - бұл кез келген ортақ ресурсқа бірнеше ағындардың қатынасын басқару мүмкіндігі. Бірнеше ағындар бір тапсырманы орындауға тырысқанда, қате нәтиже алу мүмкіндігі бар, сондықтан бұл мәселені шешу үшін Java синхрондауды пайдаланады, соның арқасында бір уақытта тек бір ағын жұмыс істей алады. Синхронизацияны үш жолмен жүзеге асыруға болады:
  • Синхрондау әдісі
  • Белгілі бір блокты синхрондау арқылы
  • Статикалық синхрондау

Әдісті синхрондау

Синхрондалған әдіс кез келген ортақ ресурс үшін нысанды құлыптау үшін пайдаланылады. Ағын синхрондалған әдісті шақырғанда, ол автоматты түрде сол нысанда құлыпты алады және ағын өз тапсырмасын орындаған кезде оны босатады. Оның жұмыс істеуі үшін синхрондалған кілт сөзін қосу керек . Бұл мысалмен қалай жұмыс істейтінін көрейік:
/**
* Пример, где мы синхронизируем метод. То есть добавляем ему слово synchronized.
* Есть два писателя, которые хотят использовать один принтер. Они подготовor свои поэмы
* И конечно же не хотят, чтоб их поэмы перемешались, а хотят, чтоб работа была сделана по * * * очереди для каждого из них
*/
class Printer {

   synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer  = new Printer();

       // создаем два треда
       Writer1 writer1 = new Writer1(printer);
       Writer2 writer2 = new Writer2(printer);

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

/**
* Писатель номер 1, который пишет свою поэму.
*/
class Writer1 extends Thread {
   Printer printer;

   Writer1(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<string> poem = Arrays.asList("Я ", this.getName(), " Пишу", " Письмо");
       printer.print(poem);
   }

}

/**
* Писатель номер 2, который пишет свою поэму.
*/
class Writer2 extends Thread {
   Printer printer;

   Writer2(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<String> poem = Arrays.asList("Не Я ", this.getName(), " Не пишу", " Не Письмо");
       printer.print(poem);
   }
}
Және консольге шығу:

Я Thread-0 Пишу Письмо
Не Я Thread-1 Не пишу Не Письмо

Синхрондау блогы

Синхрондалған блокты кез келген арнайы әдіс ресурсында үндестіруді орындау үшін пайдалануға болады. Үлкен әдісте (иә, иә, мұндай нәрселерді жаза алмайсыз, бірақ кейде солай болады) қандай да бір себептермен кішкене бөлікті синхрондау керек делік. Егер әдістің барлық codeтарын синхрондалған блокқа қойсаңыз, ол синхрондалған әдіс сияқты жұмыс істейді. Синтаксис келесідей көрінеді:
synchronized (“an object для блокировки”) {
   // сам code, который нужно защитить
}
Алдыңғы мысалды қайталамау үшін біз анонимді сыныптар арқылы ағындарды жасаймыз, яғни Runnable интерфейсін бірден іске асырамыз.
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

   void print(List<String> wordsToPrint) {
       synchronized (this) {
           wordsToPrint.forEach(System.out::print);
       }
       System.out.println();
   }

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer = new Printer();

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

}
және консольге шығару

Я Writer1 Пишу Письмо
Не Я Writer2 Не пишу Не Письмо

Статикалық синхрондау

Егер статикалық әдісті синхрондауды жасасаңыз, құлып нысанда емес, сыныпта болады. Бұл мысалда синхрондалған кілт сөзді статикалық синхрондауды орындау үшін статикалық әдіске қолданамыз:
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

   static synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               Printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               Printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}
және консольге шығу:

Не Я Writer2 Не пишу Не Письмо
Я Writer1 Пишу Письмо

47. Тұрақты айнымалы дегеніміз не?

Түйінді сөз volatileағынның қауіпсіздігін қамтамасыз ету үшін көп ағынды бағдарламалауда пайдаланылады, себебі бір өзгермелі айнымалының модификациясы барлық басқа ағындарға көрінеді, сондықтан бір айнымалыны бір уақытта бір ағынмен пайдалануға болады. Кілт сөзді пайдаланып, volatileайнымалының ағынды қауіпсіз болатынына және ортақ жадта сақталатынына және ағындар оны кэшке қабылдамайтынына кепілдік бере аласыз. Ол неге ұқсайды?
private volatile AtomicInteger count;
Біз жай ғана айнымалыға қосамыз volatile. Бірақ бұл жіптің толық қауіпсіздігін білдірмейді... Өйткені, операциялар айнымалыға атомдық болмауы мүмкін. AtomicБірақ операцияны атомдық түрде орындайтын кластарды, яғни процессордың бір орындауында пайдалануға болады . Көптеген осындай сыныптарды пакетте табуға болады java.util.concurrent.atomic.

48. Тұйықтық дегеніміз не

Java тіліндегі тығырықтан шығу көп ағынның бөлігі болып табылады. Тұйықталу ағын басқа ағынмен алынған нысан құлпын күтетін және екінші ағын бірінші ағынмен алынған нысан құлпын күтіп тұрған жағдайда орын алуы мүмкін. Осылайша, бұл екі ағын бір-бірін күтеді және олардың codeын орындауды жалғастырмайды. Ең жақсы 50 Java негізгі сұхбат сұрақтары мен жауаптары.  3 - 5 бөлімRunnable іске асыратын класс бар мысалды қарастырайық. Ол конструкторда екі ресурсты қабылдайды. run() әдісінің ішінде ол олар үшін құлыпты бір-бірден алады, сондықтан осы сыныптың екі нысанын жасап, ресурстарды әртүрлі ретпен тасымалдасаңыз, құлыпқа оңай кіруге болады:
class DeadLock {

   public static void main(String[] args) {
       final Integer r1 = 10;
       final Integer r2 = 15;

       DeadlockThread threadR1R2 = new DeadlockThread(r1, r2);
       DeadlockThread threadR2R1 = new DeadlockThread(r2, r1);

       new Thread(threadR1R2).start();
       new Thread(threadR2R1).start();
   }
}

/**
* Класс, который принимает два ресурса.
*/
class DeadlockThread implements Runnable {

   private final Integer r1;
   private final Integer r2;

   public DeadlockThread(Integer r1, Integer r2) {
       this.r1 = r1;
       this.r2 = r2;
   }

   @Override
   public void run() {
       synchronized (r1) {
           System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r1);

           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }

           synchronized (r2) {
               System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r2);
           }
       }
   }
}
Консоль шығысы:

Первый тред захватил первый ресурс
Второй тред захватывает второй ресурс

49. Тығырықтан қалай құтылуға болады?

Тығырықтың қалай болатынын білетінімізге сүйене отырып, біз кейбір қорытындылар жасай аламыз ...
  • Жоғарыдағы мысалда көрсетілгендей, тығырықтан шығу құлыптардың ұя салуына байланысты болды. Яғни, бір құлыптың ішінде екіншісі немесе одан да көп. Мұны келесі жолмен болдырмауға болады - ұя салудың орнына, үстіне жаңа абстракция қосып, құлыпты жоғары деңгейге беру керек және кірістірілген құлыптарды алып тастау керек.
  • Неғұрлым бұғаттау болса, соғұрлым тығырықтан шығу мүмкіндігі артады. Сондықтан, құлып қосқан сайын, оның шынымен қажет пе және жаңасын қосуды болдырмауға болатынын ойлау керек.
  • Қолданады Thread.join(). Тұйықталу бір ағын екіншісін күтіп тұрғанда да жасалуы мүмкін. join()Бұл мәселені болдырмау үшін әдіске уақыт шегін орнатуды қарастыруға болады .
  • Егер бізде бір жіп болса, тығырықтан шығу болмайды;)

50. Жарыс шарты дегеніміз не?

Егер нақты жарыстарда автомобильдер өнер көрсетсе, онда көп ағынның жарыс терминологиясында жіптер жарыстарда орындайды. Бірақ неге? Жұмыс істеп тұрған және бір нысанға қатынаса алатын екі ағын бар. Және олар бір уақытта күйді жаңартуға тырысуы мүмкін. Әзірге бәрі түсінікті, солай ма? Сонымен, ағындар нақты параллельді (егер процессорда бірнеше ядро ​​болса) немесе процессор қысқа уақыт кезеңін бөлген кезде шартты түрде параллель жұмыс істейді. Және біз бұл процестерді басқара алмаймыз, сондықтан бір ағын нысаннан деректерді оқығанда, оны басқа бір ағын жасағанға дейін өзгертуге уақыты болатынына кепілдік бере алмаймыз. Осындай проблемалар сынақ пен әрекеттің тіркесімі өткенде орын алады. Бұл нені білдіреді? Мысалы, бізде ifшарттың өзі өзгеретін денеде өрнек бар, яғни:
int z = 0;

// проверь
if (z < 5) {
//действуй
   z = z + 5;
}
Сонымен, z әлі де нөлге тең және олар бірге бұл мәнді өзгерткен кезде екі ағын осы code блогын бір уақытта енгізетін жағдай болуы мүмкін. Ақыр соңында біз күтілетін 5 емес, 10 мәнін аламыз. Мұны қалай болдырмауға болады? Орындауға дейін және кейін құлыптау керек. Яғни, блокқа кіру үшін бірінші ағын үшін if, барлық әрекеттерді орындаңыз, оны өзгертіңіз, zсодан кейін ғана келесі ағынға мұны істеу мүмкіндігін беріңіз. Бірақ келесі ағын блокқа кірмейді if, себебі zол қазірдің өзінде 5-ке тең болады:
// получить блокировку для z
if (z < 5) {
   z = z + 5;
}
// выпустить из блокировки z
===================================================

Шығарудың орнына

Соңына дейін оқыған жандарға алғыс айтқым келеді. Бұл ұзақ сапар болды және сіз оған жеттіңіз! Барлығы анық болмауы мүмкін. Бұл жақсы. Мен Java тілін үйрене бастағанда, мен статикалық айнымалының не екенін біле алмадым. Бірақ ештеңе жоқ, мен осы оймен ұйықтадым, тағы бірнеше дереккөзді оқып, ақыры түсіндім. Әңгімелесуге дайындалу практикалық емес, академиялық мәселе болып табылады. Сондықтан, әр сұхбат алдында сіз жиі пайдаланbyteын нәрселерді қайталап, жадыңызды жаңартуыңыз керек.

Әдеттегідей, пайдалы сілтемелер:

Оқығандарыңызға рахмет, Жақында кездескенше) GitHub-тағы профилім
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION