JavaRush /Blog Jawa /Random-JV /Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban. Bagean ...

Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban. Bagean 3

Diterbitake ing grup
Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban. Part 1 Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban. Bagean 2

Multithreading

37. Kepriye carane nggawe serat (alur) anyar ing basa Jawa?

Salah siji cara utawa liyane, nggawe liwat nggunakake kelas Utas. Nanging bisa uga ana pilihan ing kene ...
  1. We warisan sakajava.lang.Thread
  2. We ngleksanakake antarmuka kang obyek nampa kelas java.lang.RunnablekonstruktorThread
Ayo dadi pirembagan bab saben wong.

We warisan saka kelas Utas

Kanggo nggawe karya iki, ing kelas kita warisan saka java.lang.Thread. Isine meth run(), sing persis sing kita butuhake. Kabeh urip lan logika thread anyar bakal ana ing metode iki. Iki minangka maincara kanggo thread anyar. Sawise iki, kabeh sing isih ana yaiku nggawe obyek saka kelas kita lan nglakokake metode kasebut start(), sing bakal nggawe thread anyar lan mbukak logika sing ditulis ing kono. Ayo katon:
/**
* Пример того, 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();
   }
}
Output menyang console bakal kaya iki:

Thread-1
Thread-0
Thread-2
Yaiku, sanajan ing kene kita ndeleng manawa benang dieksekusi ora kanthi giliran, nanging minangka JVM mutusake)

Ngleksanakake antarmuka Runnable

Yen sampeyan nglawan warisan lan / utawa wis oleh warisan salah siji saka kelas liyane, sampeyan bisa nggunakake java.lang.Runnable. Kene ing kelas kita ngleksanakake antarmuka iki lan ngleksanakake cara run(), kaya ing conto kasebut. Sampeyan mung kudu nggawe obyek liyane Thread. Iku bakal katon sing luwih garis luwih elek. Nanging kita ngerti manawa warisan mbebayani lan luwih becik dihindari kanthi cara apa wae;) Ayo goleki:
/**
* Пример того, 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();
   }
}
Lan asil eksekusi:

Thread-0
Thread-1
Thread-2

38. Apa bedane proses lan benang?

Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban.  Bagean 3 - 1Ana beda ing ngisor iki antarane proses lan utas:
  1. Program sing dieksekusi diarani proses, dene Utas minangka subset saka proses.
  2. Proses kasebut independen, dene benang minangka subset saka proses.
  3. Proses duwe ruang alamat sing beda ing memori, dene benang ngemot ruang alamat umum.
  4. Ngalih konteks luwih cepet ing antarane benang dibandhingake karo proses.
  5. Komunikasi antarproses luwih alon lan luwih larang tinimbang komunikasi interthread.
  6. Sembarang owah-owahan ing proses induk ora mengaruhi proses anak, dene owah-owahan ing benang induk bisa mengaruhi benang anak.

39. Apa kaluwihan saka multithreading?

Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban.  Bagean 3 - 2
  1. Multithreading ngidini aplikasi / program tansah nanggapi input sanajan wis mlaku sawetara tugas latar mburi;
  2. Multithreading ngidini sampeyan ngrampungake tugas kanthi luwih cepet amarga benang dieksekusi kanthi mandiri;
  3. Multithreading nyedhiyakake panggunaan cache sing luwih apik amarga benang nuduhake sumber memori umum;
  4. Multithreading nyuda jumlah server sing dibutuhake amarga siji server bisa mbukak pirang-pirang thread bebarengan.

40. Apa kahanan ing siklus urip benang?

Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban.  Bagean 3 - 3
  1. Anyar: Ing negara iki, obyek kelas Threaddigawe nggunakake operator anyar, nanging thread ora ana. Utas ora diwiwiti nganti kita nelpon start().
  2. Runnable: Ing negara iki, thread wis siyap kanggo mbukak sawise nelpon cara wiwit (). Nanging, durung dipilih dening panjadwal thread.
  3. Running: Ing negara iki, panjadwal thread milih thread saka negara siap lan mlaku.
  4. Nunggu / Diblokir: Ing kahanan iki, utas ora mlaku nanging isih urip utawa ngenteni utas liyane rampung.
  5. Mati / Dipungkasi: Nalika metode kasebut metu, run()benang ana ing kahanan mandheg utawa mati.

41. Apa bisa miwiti thread kaping pindho?

Ora, kita ora bisa miwiti maneh utas amarga sawise utas diwiwiti lan dieksekusi, bakal dadi negara Mati. Dadi yen kita nyoba kanggo mbukak thread kaping pindho, iku bakal uncalan runtimeException " java.lang.IllegalThreadStateException ". Ayo katon:
class DoubleStartThreadExample extends Thread {

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

   /**
    * Запускаем тред дважды
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
Sanalika karya tekan wiwitan kapindho ing thread padha, banjur bakal ana pangecualian. Coba dhewe;) luwih becik ndeleng sapisan tinimbang krungu kaping satus.

42. Apa yen sampeyan nelpon cara roto () langsung tanpa nelpon wiwitan () cara?

Ya, run()mesthine sampeyan bisa nelpon cara, nanging iki ora bakal nggawe thread anyar lan nglakokake minangka thread kapisah. Ing kasus iki, iku obyek prasaja sing nelpon cara prasaja. Yen kita ngomong babagan cara start(), mula beda. Kanthi ngluncurake metode iki, runtimengluncurake sing anyar lan, kanthi cara iki, nganggo metode kita;) Yen sampeyan ora ngandel, coba:
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();
   }
}
Lan output menyang console bakal kaya iki:

0123401234
Bisa dideleng yen ora ana thread sing digawe. Kabeh bisa kaya kelas normal. Pisanan cara kelas siji makarya, banjur kaloro.

43. Apa benang daemon?

Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban.  Bagean 3 - 4Utas Daemon (sabanjuré diarani Utas Daemon) ya iku Utas sing nglakokaké tugas ing latar mburi gegayutan karo Utas liya. Tegese, tugase kanggo nindakake tugas tambahan sing kudu ditindakake mung bebarengan karo utas liyane (utama). Ana akeh benang daemon sing bisa digunakake kanthi otomatis, kayata Garbage Collector, finalizer, lsp.

Kenapa Jawa nutup thread daemon?

Tujuan mung utas daemon yaiku nyedhiyakake layanan menyang utas pangguna kanggo tugas dhukungan latar mburi. Mulane, yen utas utama wis rampung, banjur runtime kanthi otomatis nutup kabeh thread daemon sawijining.

Cara kanggo nggarap kelas Utas

Kelas kasebut java.lang.Threadnyedhiyakake rong cara kanggo nggarap daemon benang:
  1. public void setDaemon(boolean status)- nuduhake yen iki bakal dadi benang daemon. Default yaiku false, sing tegese benang non-daemon bakal digawe kajaba ditemtokake kanthi kapisah.
  2. public boolean isDaemon()- ateges iki getter kanggo variabel daemonsing kita nyetel nggunakake cara sadurunge.
Tuladha:
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();
   }
}
Output konsol:

демон?.. true
демон?.. false
демон?.. false
daemon thread
user thread
user thread
Saka output, kita bisa ndeleng manawa ana ing benang dhewe, nggunakake currentThread()metode statis, kita bisa ngerteni apa benang ing tangan siji, ing tangan liyane, yen kita duwe referensi kanggo obyek thread iki, kita bisa ngerteni. langsung saka iku. Iki menehi keluwesan sing dibutuhake ing konfigurasi.

44. Apa bisa nggawe benang dadi daemon sawise digawe?

Ora. Yen sampeyan nindakake iki bakal mbuwang pangecualian IllegalThreadStateException. Mula, kita mung bisa nggawe utas daemon sadurunge diwiwiti. Tuladha:
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);
   }
}
Output konsol:

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

45. Apa iku shutdownhook?

Shutdownhook minangka utas sing diarani sacara implisit sadurunge JVM (Java Virtual Machine) mati. Supaya kita bisa nggunakake kanggo ngresiki sumber utawa nyimpen negara nalika Java Virtual Machine mati normal utawa dumadakan. Kita bisa nambah shutdown hooknggunakake cara ing ngisor iki:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Kaya sing dituduhake ing conto:
/**
* Программа, которая показывает 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();
       }
   }
}
Output konsol:

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

46. ​​Apa sing diarani sinkronisasi?

Sinkronisasi ing Jawa yaiku kemampuan kanggo ngontrol akses pirang-pirang benang menyang sumber daya sing dienggo bareng. Nalika pirang-pirang utas nyoba nindakake tugas sing padha, ana kemungkinan asil sing salah, mula kanggo ngatasi masalah iki, Jawa nggunakake sinkronisasi, amarga mung siji utas sing bisa digunakake. Sinkronisasi bisa ditindakake kanthi telung cara:
  • Metode Sinkronisasi
  • Kanthi nyinkronake blok tartamtu
  • Sinkronisasi statis

Metode sinkronisasi

Cara sing disinkronake digunakake kanggo ngunci obyek kanggo sumber daya sing dienggo bareng. Nalika thread nelpon cara sing disinkronake, kanthi otomatis entuk kunci ing obyek kasebut lan ngeculake nalika thread ngrampungake tugase. Supaya bisa digunakake, sampeyan kudu nambah tembung kunci sing disinkronake . Ayo ndeleng kepiye cara iki nganggo conto:
/**
* Пример, где мы синхронизируем метод. То есть добавляем ему слово 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);
   }
}
Lan output menyang console:

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

Blok sinkronisasi

Blok sing disinkronake bisa digunakake kanggo nindakake sinkronisasi ing sembarang sumber cara tartamtu. Ayo dadi ngomong yen ing cara gedhe (ya, ya, sampeyan ora bisa nulis bab kuwi, nanging kadhangkala mengkono) sampeyan kudu nyinkronake mung bagean cilik, sakperangan alesan. Yen sampeyan nglebokake kabeh kode cara ing blok sing disinkronake, bakal padha karo cara sing disinkronake. Sintaks katon kaya iki:
synchronized (“an object для блокировки”) {
   // сам code, который нужно защитить
}
Supaya ora mbaleni conto sadurunge, kita bakal nggawe thread liwat kelas anonim - sing langsung ngleksanakake antarmuka 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();
   }
}

}
lan output menyang console

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

Sinkronisasi statis

Yen sampeyan nggawe cara statis diselarasake, kunci bakal ing kelas, ora ing obyek. Ing conto iki, kita nggunakake tembung kunci sing disinkronake menyang cara statis kanggo nindakake sinkronisasi statis:
/**
* Вот 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();
   }
}
lan output menyang konsol:

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

47. Apa variabel volatile?

Tembung kunci volatiledigunakake ing program multi-threaded kanggo nyedhiyakake safety thread amarga modifikasi siji variabel sing bisa diowahi katon ing kabeh thread liyane, saengga siji variabel bisa digunakake dening siji thread sekaligus. Nggunakake tembung kunci, volatilesampeyan bisa njamin yen variabel kasebut aman kanggo benang lan bakal disimpen ing memori sing dienggo bareng, lan benang ora bakal dilebokake ing cache. Apa sing katon kaya?
private volatile AtomicInteger count;
Kita mung nambah menyang variabel volatile. Nanging iki ora ateges safety thread lengkap ... Sawise kabeh, operasi bisa uga ora atom ing variabel. Nanging sampeyan bisa nggunakake Atomickelas sing nindakake operasi atom, yaiku, ing siji eksekusi dening prosesor. Akeh kelas kasebut bisa ditemokake ing paket kasebut java.util.concurrent.atomic.

48. Apa buntu

Deadlock ing Jawa minangka bagéan saka multithreading. Kebuntuan bisa kedadeyan ing kahanan nalika benang ngenteni kunci obyek sing dipikolehi dening benang liyane, lan benang kapindho nunggu kunci obyek sing dipikolehi dening benang pertama. Mangkono, loro utas iki ngenteni saben liyane lan ora bakal terus ngeksekusi kode kasebut. Top 50 Pitakonan Wawancara Inti Jawa lan Jawaban.  Bagean 3 - 5Ayo goleki Conto sing ana kelas sing ngetrapake Runnable. Iku nampa loro sumber daya ing sawijining konstruktor. Nang cara roto (), njupuk kunci kanggo wong-wong mau siji, supaya yen sampeyan nggawe loro obyek saka kelas iki lan nransfer sumber daya ing pesenan beda, sampeyan bisa kanthi gampang mbukak menyang kunci:
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);
           }
       }
   }
}
Output konsol:

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

49. Kepriye carane supaya ora buntu?

Adhedhasar apa sing kita ngerti kepiye kedadeyan deadlock, kita bisa nggawe kesimpulan ...
  • Kaya sing dituduhake ing conto ing ndhuwur, deadlock amarga nesting kunci. Tegese, ing jero siji kunci ana liyane utawa luwih. Sampeyan bisa ngindhari iki kanthi cara ing ngisor iki - tinimbang nesting, sampeyan kudu nambah abstraksi anyar ing ndhuwur lan menehi kunci menyang tingkat sing luwih dhuwur, lan mbusak kunci nested.
  • Sing liyane pamblokiran ana, luwih gedhe kasempatan sing bakal ana deadlock. Mulane, saben-saben sampeyan nambah kunci, sampeyan kudu mikir apa pancene perlu lan apa nambah sing anyar bisa nyingkiri.
  • Migunakake Thread.join(). A deadlock uga bisa rampung nalika siji thread nunggu liyane. Kanggo ngindhari masalah iki, sampeyan bisa nimbang nyetel watesan wektu ing join()metode kasebut.
  • Yen kita duwe siji thread, ora bakal ana deadlock;)

50. Apa kahanan lomba?

Yen ing balapan nyata mobil nindakake, banjur ing terminologi racing multi-threading, Utas nindakake ing balapan. Nanging kenapa? Ana rong utas sing mlaku lan bisa duwe akses menyang obyek sing padha. Lan padha bisa nyoba nganyari negara ing wektu sing padha. Nganti saiki kabeh wis jelas, ta? Dadi Utas bisa digunakake ing podo karo nyata (yen ana luwih saka siji inti ing prosesor) utawa kondisi podo karo, nalika prosesor allocates wektu cendhak. Lan kita ora bisa ngontrol proses kasebut, mula kita ora bisa njamin yen siji thread maca data saka obyek, bakal duwe wektu kanggo ngganti sadurunge sawetara thread liyane nindakake. Masalah kaya iki kedadeyan nalika kombinasi test-lan-tumindak iki liwati. Iki artine apa? Contone, kita duwe ifekspresi ing awak sing kondisi kasebut diganti, yaiku:
int z = 0;

// проверь
if (z < 5) {
//действуй
   z = z + 5;
}
Supaya ana uga kahanan nalika loro Utas bebarengan ngetik pemblokiran kode iki ing wektu nalika z isih padha karo nul lan bebarengan padha ngganti nilai iki. Lan ing pungkasan kita ora bakal entuk nilai sing dikarepake 5, nanging 10. Kepiye carane supaya ora? Sampeyan kudu ngunci sadurunge lan sawise eksekusi. Yaiku, kanggo thread pisanan mlebu blok if, nindakake kabeh tumindak, ngganti, zlan mung banjur menehi thread sabanjuré kesempatan kanggo nindakake iki. Nanging utas sabanjure ora bakal mlebu blok kasebut if, amarga zwis padha karo 5:
// получить блокировку для z
if (z < 5) {
   z = z + 5;
}
// выпустить из блокировки z
===================================================

Tinimbang output

Aku pengin matur nuwun kanggo kabeh sing maca nganti pungkasan. Iku lelampahan dawa lan sampeyan wis rampung! Ora kabeh bisa dadi cetha. Iki apik. Sanalika aku miwiti sinau basa Jawa, aku ora bisa mbungkus sirahku babagan apa variabel statis. Nanging ora ana, aku turu karo pikirane iki, maca sawetara sumber liyane lan pungkasane ngerti. Nyiapake wawancara luwih akeh babagan akademik tinimbang praktis. Mula, sadurunge saben wawancara, sampeyan kudu mbaleni lan nyegerake memori babagan perkara sing ora asring digunakake.

Lan kaya biasane, pranala migunani:

Matur nuwun kabeh kanggo maca, Sampai ketemu) Profilku ing GitHub
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION