103. Мұрагерлікте ерекшеліктерді тексеру ережелері қандай?
Егер мен сұрақты дұрыс түсінсем, олар мұрагерлік кезінде ерекше жағдайлармен жұмыс істеу ережелері туралы сұрайды және олар келесідей:- Тұқымдағы/іске асырудағы қайта анықталған немесе іске асырылған әдіс иерархияда суперкласс/интерфейс әдісіндегі ерекшеліктерге қарағанда жоғарырақ тексерілген ерекшеліктерді шығара алмайды.
public interface Animal {
void voice() throws IOException;
}
Бұл интерфейсті іске асыруда біз жалпы шығарылған ерекшелікті (мысалы, Exception , Throwable ) шығара алмаймыз, бірақ оны FileNotFoundException сияқты ұрпақты ерекшелікпен ауыстыра аламыз :
public class Cat implements Animal {
@Override
public void voice() throws FileNotFoundException {
// некоторая реализация
}
}
- Ішкі класс конструкторы an objectіні жасау кезінде шақырылатын суперкласс конструкторы шығарған барлық ерекшелік кластарын лақтыру блоктарына қосуы керек.
public class Animal {
public Animal() throws ArithmeticException, NullPointerException, IOException {
}
Содан кейін сынып мұрагері оларды конструкторда көрсетуі керек:
public class Cat extends Animal {
public Cat() throws ArithmeticException, NullPointerException, IOException {
super();
}
Немесе әдістер жағдайындағыдай, бірдей ерекшеліктерді емес, жалпыламаларды көрсетуге болады. Біздің жағдайда жалпы ерекшелікті көрсету жеткілікті болады - Ерекшелік , өйткені бұл қарастырылған барлық үш ерекшеліктің ортақ атасы:
public class Cat extends Animal {
public Cat() throws Exception {
super();
}
104. Finally блогы орындалмайтын уақыттың codeын жаза аласыз ба?
Алдымен, ақыры не екенін еске түсірейік . Бұрын біз ерекше жағдайларды ұстау механизмін қарастырдық: try блогы ұстау аймағын белгілейді, ал ұстау блогы(лар) ы белгілі бір ерекшелік тасталған кезде жұмыс істейтін code болып табылады. Ақырында, codeтың үшінші блогы, ақырында, ол catch- пен ауыстырылады , бірақ бір-бірін жоққа шығармайды. Бұл блоктың мәні мынада: ондағы code әрқашан тырысу немесе ұстау нәтижесіне қарамастан жұмыс істейді (ерекшелік тасталды ма, жоқ па). Оның сәтсіздігі жағдайлары өте сирек кездеседі және олар қалыпты емес. Сәтсіздіктің ең қарапайым жағдайы жоғарыдағы codeта System.exit(0) әдісі шақырылады , ол бағдарламаны тоқтатады (оны өшіреді):try {
throw new IOException();
} catch (IOException e) {
System.exit(0);
} finally {
System.out.println("Данное сообщение не будет выведенно в консоль");
}
Соңында жұмыс істемейтін басқа да жағдайлар бар :
- Жүйенің маңызды ақауларынан туындаған бағдарламаның қалыптан тыс аяқталуы немесе қолданбаны «бұзатын» кейбір Қатенің құлауы (қатенің мысалы стектің жады толып кеткен кезде пайда болатын бірдей StackOwerflowError болуы мүмкін).
- Deamon жібі ry арқылы өткенде ... соңында блоктау және осыған параллель бағдарлама аяқталады. Өйткені, деамон жіпі фондық әрекеттерге арналған жіп болып табылады, яғни бұл басымдық және міндетті емес және қолданба өз жұмысының аяқталуын күтпейді.
- try немесе catch ішіндегі ең кең таралған шексіз цикл , бір рет ағын сонда мәңгі қалады:
try { while (true) { } } finally { System.out.println("Данное сообщение не будет выведенно в консоль"); }
105. Бір catch блогында бірнеше ерекшеліктерді өңдеу мысалын жазыңыз
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 блогы сәтті болса, ол ерекше жағдайды өңдеу құқығын алады, ал төменде қалған блоктар енді болмайды. оны ұстауға тырысып, оны өзінше өңдеуге қабілетті. Сондықтан, тар ерекшеліктер аулау блок тізбегінде жоғарырақ , ал кеңірек ерекшеліктер төменірек орналастырылады. Мысалы, егер біздің бірінші catch блогында Exception класының ерекше жағдайы ұсталса , онда тексерілген ерекшеліктер қалған блоктарға кіре алмайды ( 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 әдісі арқылы оның нақты түрін анықтауға тырысамыз , осылайша кейінірек оны теріс салдарсыз осы түрге дейін тарылта аламыз. Қарастырылған екі тәсілді де бір жағдайда қолдануға болады, бірақ мен сұрақтың дұрыс емес екенін айттым, өйткені мен екінші нұсқаны жақсы деп атамас едім және оны өз тәжірибемде ешқашан көрмегенмін, сонымен бірге мультикарттармен бірінші әдіс кеңінен таралған. назар аудару.
106. Қай оператор ерекше жағдайды мәжбүрлеп шығаруға мүмкіндік береді? Мысал жаз
Мен оны жоғарыда бірнеше рет қолдандым, бірақ соған қарамастан мен бұл кілт сөзді қайталаймын - throw . Қолдану мысалы (ерекше жағдайды мәжбүрлеу):throw new NullPointerException();
107. Негізгі әдіс лақтыратын ерекше жағдайды шығара ала ма? Олай болса, қайда аударылады?
Ең алдымен, мен негізгі қарапайым әдістен басқа ештеңе емес екенін атап өткім келеді, иә, оны виртуалды машина бағдарламаны орындауды бастау үшін шақырады, бірақ бұдан басқа оны кез келген басқа codeтан шақыруға болады. Яғни, ол тастағаннан кейін тексерілген ерекшеліктерді көрсетудің әдеттегі ережелеріне бағынады :public static void main(String[] args) throws IOException {
Тиісінше, онда ерекшеліктер де болуы мүмкін. Егер main қандай да бір әдіспен шақырылмаса, бірақ бағдарламаны іске қосу нүктесі ретінде іске қосылған болса, онда ол шығарған ерекшелік .UncaughtExceptionHandler интерцепторы арқылы өңделеді . Бұл өңдегіш әр ағында бір (яғни әрбір ағында бір өңдеуші). Қажет болса, сіз өзіңіздің өңдегішті жасай аласыз және оны Thread нысанында шақырылған setDefaultUncaughtExceptionHandler әдісі арқылы орната аласыз .
Көп ағынды
108. Көп ағынмен жұмыс істеуге арналған қандай құралдарды білесіз?
Java-де көп ағынды пайдаланудың негізгі/негізгі құралдары:- Синхрондалған – басқа ағындардан ағын кірген кезде әдісті/блокты жабу (блоктау) механизмі.
- Ұшқыш - әртүрлі ағындар арқылы айнымалыға дәйекті қол жеткізуді қамтамасыз ету механизмі, яғни айнымалыда осы модификатордың болуымен барлық тағайындау және оқу операциялары атомдық болуы керек. Басқаша айтқанда, ағындар бұл айнымалыны жергілікті жадына көшірмейді және оны өзгертпейді, бірақ оның бастапқы мәнін өзгертеді.
- Runnable - белгілі бір сыныпта іске асырылуы мүмкін интерфейс (атап айтқанда, оның іске қосу әдісі):
public class CustomRunnable implements Runnable {
@Override
public void run() {
// некоторая логика
}
}
Осы сыныптың an objectісін жасағаннан кейін, осы нысанды жаңа Thread нысанының конструкторында орнату және оның start() әдісін шақыру арқылы жаңа ағынды бастауға болады :
Runnable runnable = new CustomRunnable();
new Thread(runnable).start();
Бастау әдісі іске асырылған run() әдісін бөлек ағында іске қосады.
- Thread - мұраға алатын класс ( іске қосу әдісін қайта анықтау кезінде ):
public class CustomThread extends Thread {
@Override
public void run() {
// некоторая логика
}
}
Осы сыныптың an objectісін жасау және оны start() әдісі арқылы іске қосу арқылы біз жаңа ағынды іске қосамыз:
new CustomThread().start();
- Concurrency – көп ағынды ортада жұмыс істеуге арналған құралдары бар пакет.
- Concurrent Collections – көп ағынды ортада жұмыс істеуге мамандандырылған жинақтар жиынтығы.
- Кезектер – көп ағынды орта үшін мамандандырылған кезектер (блоктау және бұғаттамайтын).
- Синхронизаторлар - көп ағынды ортада жұмыс істеуге арналған арнайы утorталар.
- Орындаушылар жіп пулдарын құру механизмдері болып табылады.
- Құлыптар - жіптерді синхрондау механизмдері (стандарттыларға қарағанда икемді - синхрондалған, күту, хабарлау, барлығын хабарлау).
- Атомдар – көп ағынды орындау үшін оңтайландырылған сыныптар; әрбір операция атомдық болып табылады.
109. Жіптер арасындағы синхрондау туралы айту. wait(), notify() - notifyAll() join() әдістері не үшін қолданылады?
Сұрақты түсінуімше, ағындар арасындағы синхрондау кілт модификаторы туралы - синхрондалған . Бұл модификаторды тікелей блоктың жанында орналастыруға болады:synchronized (Main.class) {
// некоторая логика
}
Немесе тікелей әдіс қолтаңбасында:
public synchronized void move() {
// некоторая логика}
Жоғарыда айтқанымдай, синхрондалған – бір ағын енгізілген кезде басқа ағындардан блокты/әдісті жабуға мүмкіндік беретін механизм. Блокты/әдісті бөлме ретінде қарастырыңыз. Кейбір ағындар оған келіп, оған кіріп, оны құлыптайды, ал басқа ағындар бөлмеге келіп, оның жабық екенін көріп, бос болғанша оның жанында күтеді. Өз ісін орындап, бірінші жіп бөлмеден шығып, кілтті босатады. Мен кілт туралы үнемі айтқаным бекер емес еді, өйткені ол шынымен бар. Бұл бос емес/бос күйі бар арнайы нысан. Бұл нысан әрбір Java нысанына бекітілген, сондықтан синхрондалған блокты пайдаланған кезде біз жақшаның ішінде мутексі есікті жапқымыз келетін нысанды көрсетуіміз керек:
Cat cat = new Cat();
synchronized (cat) {
// некоторая логика
}
Сондай-ақ, бірінші мысалда ( Main.class ) жасағанымдай, класс мутексін пайдалануға болады. Әдіс бойынша синхрондауды пайдаланған кезде біз жабылғымыз келетін нысанды көрсетпейміз, солай ма? Бұл жағдайда, статикалық емес әдіс үшін ол this нысанының мутексінде , яғни осы сыныптың ағымдағы нысанында жабылады. Статикалық класс ағымдағы сыныптың мутексінде жабылады ( this.getClass(); ). Мутекс туралы толығырақ мына жерден оқи аласыз . Синхрондалған туралы мына жерден оқыңыз . Wait() – мутексті босатып, ағымдағы мониторға (зәкір сияқты нәрсе) қосылған сияқты ағымдағы ағынды күту режиміне қоятын әдіс. Осыған байланысты бұл әдісті тек синхрондалған блоктан немесе әдістен шақыруға болады (әйтпесе, ол нені босатуы керек және ол нені күтуі керек). Сондай-ақ, бұл Object класының әдісі екенін ескеріңіз . Дәлірек айтқанда, бір емес, тіпті үшеуі:
-
Wait() – ағымдағы ағынды басқа ағын осы нысан үшін notify() немесе notifyAll() әдісін шақырғанша күту режиміне қояды (бұл әдістер туралы кейінірек айтатын боламыз).
-
Күту (ұзақ күту уақыты) - басқа ағын осы нысандағы notify() немесе notifyAll() әдісін шақырғанша немесе көрсетілген күту уақыты біткенше ағымдағы ағынды күту режиміне қояды .
-
Күту (ұзақ күту уақыты, int nanos) - алдыңғыға ұқсас, тек нанос наносекундтарды көрсетуге мүмкіндік береді (нақтырақ уақыт параметрі).
-
Notify() - ағымдағы синхрондау блогының бір кездейсоқ ағынын оятуға мүмкіндік беретін әдіс. Тағы да, оны тек синхрондалған блокта немесе әдісте шақыруға болады (басқа жерлерде оны босату үшін ешкім болмайды).
-
NotifyAll() — ағымдағы монитордағы барлық күту ағындарын оятатын әдіс (сонымен қатар тек синхрондалған блокта немесе әдісте қолданылады).
110. Ағынды қалай тоқтатуға болады?
Бірінші айта кететін нәрсе, run() әдісі толығымен орындалғанда , ағын автоматты түрде жойылады. Бірақ кейде бұл әдіс аяқталмай тұрып, оны мерзімінен бұрын өлтіру керек. Сонда не істеуіміз керек? Thread нысанында stop() әдісі болуы керек шығар ? Қалай болса да! Бұл әдіс ескірген болып саналады және жүйенің бұзылуына әкелуі мүмкін. Ал, сонда ше? Мұны істеудің екі жолы бар: Біріншісі - ішкі логикалық жалауды пайдалану. Мысал қарастырайық. Бізде толығымен тоқтағанша экранда белгілі бір фразаны көрсетуі керек ағынды өзіміздің іске асыруымыз бар: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("Конец выполнения программы");
Нәтижесінде біз консольде келесідей нәрсені көреміз:
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 жазамыз және дайын, стандартты функционалдылықты көбірек қолданамыз. Міне, біз бүгін тоқталамыз.
GO TO FULL VERSION