111. Kepiye carane ngganti data antarane benang?
Kanggo ngganti data ing antarane benang, sampeyan bisa nggunakake macem-macem pendekatan lan cara: contone, nggunakake variabel atom, koleksi sing disinkronake, lan semafor. Nanging kanggo ngatasi masalah iki, aku bakal menehi conto karo Exchanger . Exchanger minangka kelas sinkronisasi saka paket bebarengan sing nggampangake ijol-ijolan unsur ing antarane sepasang benang kanthi nggawe titik sinkronisasi umum. Panggunaan kasebut nyederhanakake ijol-ijolan data ing antarane rong utas. Cara kerjane cukup prasaja: ngenteni rong utas sing kapisah kanggo nelpon metode exchange() . Soko kaya titik ijol-ijolan digawe ing antarane: utas pisanan nempatake obyek lan nampa obyek liyane, lan sing terakhir, banjur nampa obyek sing pisanan lan sijine dhewe. Sing, thread pisanan nggunakake exchange () cara lan nganggur nganti thread liyane nelpon exchange () cara ing obyek padha lan data diijolke antarane wong-wong mau. Minangka conto, nimbang implementasine saka kelas Utas ing ngisor iki :public class CustomThread extends Thread {
private String threadName;
private String message;
private Exchanger<String> exchanger;
public CustomThread(String threadName, Exchanger<String> exchanger) {
this.threadName = threadName;
this.exchanger = exchanger;
}
public void setMessage(final String message) {
this.message = message;
}
@Override
public void run() {
while (true) {
try {
message = exchanger.exchange(message);
System.out.println(threadName + " поток получил сообщение: " + message);
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Ing konstruktor thread, kita nemtokake obyek Exchanger sing nampa obyek saka jinis String , lan ing wiwitan (ing cara roto ) kita nggunakake exchange () kanggo pesen exchange karo thread liyane sing nggunakake cara iki ing Exchanger padha . Ayo mbukak ing utama :
Exchanger<String> exchanger = new Exchanger<>();
CustomThread first = new CustomThread("Первый ", exchanger);
first.setMessage("Сообщение первого потока");
CustomThread second = new CustomThread("Второй", exchanger);
second.setMessage("Сообщение второго потока");
first.start();
second.start();
Konsol bakal nampilake:
112. Apa prabédan antarane kelas Utas lan antarmuka Runnable?
Wangsulan: Bab ingkang pisanan aku bakal Wigati iku Utas iku kelas, Runnable antarmuka, kang prabédan banget ketok = D Aku uga bakal ngomong sing Utas nggunakake Runnable (komposisi). Yaiku, kita duwe rong cara:-
Warisan saka Utas , timpa cara roto, banjur nggawe obyek iki lan miwiti Utas liwat cara wiwitan () .
-
Ngleksanakake Runnable ing kelas tartamtu, ngleksanakake cara run () lan banjur nggawe obyek Utas , nemtokake implementasine obyek iki antarmuka Runnable kanggo konstruktor sawijining . Inggih, ing pungkasan, bukak obyek Utas nggunakake metode wiwitan () .
-
Nalika sampeyan ngleksanakake antarmuka Runnable , sampeyan ora ngganti prilaku thread. Ateges sampeyan mung menehi thread soko kanggo mbukak. Lan iki minangka komposisi kita, sing dianggep minangka pendekatan sing apik.
-
ngleksanakake Runnable menehi luwih keluwesan kanggo kelas. Yen sampeyan entuk warisan saka Utas , tumindak sing sampeyan lakoni bakal tansah ana ing Utas. Nanging yen sampeyan ngleksanakake Runnable ora kudu mung benang. Sawise kabeh, sampeyan bisa mbukak ing thread utawa ngirim menyang sawetara layanan eksekutor. Inggih, utawa mung pass nang endi wae minangka tugas ing aplikasi single-threaded.
-
Nggunakake Runnable ngidini sampeyan misahake eksekusi tugas kanthi logis saka logika kontrol benang.
-
Ing Jawa, mung siji warisan, mula mung siji kelas sing bisa ditambah. Ing wektu sing padha, jumlah antarmuka sing bisa digedhekake ora ana watesan (uga, ora cukup winates, nanging 65535 , nanging sampeyan ora bakal bisa ngetung watesan iki).
113. Ana benang T1, T2 lan T3. Carane ngleksanakake mau sequentially?
Wangsulan: Bab ingkang pisanan lan paling gampang sing teka ing atine nggunakake join() method . Iki nundha eksekusi utas saiki (sing diarani metode) nganti utas sing diarani metode kasebut rampung dieksekusi. Ayo nggawe implementasi thread kita dhewe:public class CustomThread extends Thread {
private String threadName;
public CustomThread(final String threadName){
this.threadName = threadName;
}
@Override
public void run() {
System.out.println(threadName + " - начал свою работу");
try {
// происходит некая логика
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " - закончил свою работу");
}
}
Ayo miwiti telung utas kasebut siji-siji nggunakake join() :
CustomThread t1 = new CustomThread("Первый поток");
t1.start();
t1.join();
CustomThread t2 = new CustomThread("Второй поток");
t2.start();
t2.join();
CustomThread t3 = new CustomThread("Третий поток");
t3.start();
t3.join();
Output konsol:
Tugas praktis
114. Jumlah Diagonal Matriks (masalah Leetcode)
Kahanan: Hitung jumlah kabeh unsur ing diagonal utama lan kabeh unsur ing diagonal tambahan sing dudu bagean saka diagonal utama. 1. Kanthi matriks wujud: mat = [[1,2,3], [4,5,6], [7,8,9]] Output kudu - 25 2. Kanthi matriks - mat = [[1,1,1,1], [1,1,1,1], [1,1,1,1], [1,1,1,1]] Output kudu - 8 3. Kanthi a matriks - mat = [[ 5]] Kesimpulan kudu - 5 Ngaso maca lan ngleksanakake kaputusan. Solusiku bakal dadi ing ngisor iki :public static int countDiagonalSum(int[][] matrix) {
int sum = 0;
for (int i = 0, j = matrix.length - 1; i < matrix.length; i++, j--) {
sum += matrix[i][i];
if (j != i) {
sum += matrix[i][j];
}
}
return sum;
}
Kabèh mengkono karo siji pass liwat Uploaded, sajrone kita duwe loro indeks kanggo laporan: i - kanggo nglaporake larik saka larik lan kolom saka diagonal utama, j - kanggo laporan kolom saka diagonal tambahan. Yen sel diagonal utama lan siji tambahan bertepatan, banjur salah siji saka nilai ora digatèkaké nalika ngitung jumlah. Ayo priksa nggunakake matriks saka kondisi:
int[][] arr1 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
System.out.println(countDiagonalSum(arr1));
int[][] arr2 = {
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}};
System.out.println(countDiagonalSum(arr2));
int[][] arr3 = {{5}};
System.out.println(countDiagonalSum(arr3));
Output konsol:
115. Move Zeroes (tantangan Leetcode)
Kahanan: Ing array integer, pindhah kabeh 0 menyang pungkasan, njaga urutan relatif saka unsur non-nol. 1. Kanthi array: [0,1,0,3,12] Output kudu: [1,3,12,0,0] 2. Kanthi array: [0] Output kudu: [0] Ngaso lan nulis keputusanku... Keputusanku:public static void moveZeroes(int[] nums) {
int counterWithoutNulls = 0;
int counterWithNulls = 0;
int length = nums.length;
while (counterWithNulls < length) {
if (nums[counterWithNulls] == 0) {// находим нулевые элементы и увеличиваем счётчик
counterWithNulls++;
} else { // сдвигаем элементы на количество найденных нулевых элементов слева
nums[counterWithoutNulls++] = nums[counterWithNulls++];
}
}
while (counterWithoutNulls < length) {
nums[counterWithoutNulls++] = 0;// заполняем последние элементы массива нулями согласно счётчику нулей
}
}
Ujian:
int[] arr1 = {1, 2, 0, 0, 12, 9};
moveZeroes(arr1);
System.out.println(Arrays.toString(arr1));
int[] arr2 = {0};
moveZeroes(arr2);
System.out.println(Arrays.toString(arr2));
Output konsol:
116. Diwenehi List <String> jeneng. Mbusak aksara pisanan saka saben jeneng lan muter dhaftar diurutake
1. Bab pisanan sing kudu dipikirake yaiku metode kelas Koleksi , sing ngemot akeh metode tambahan kanggo koleksi:public static List<String> processTheList(List<String> nameList) {
for (int i = 0; i < nameList.size(); i++) {
nameList.set(i, nameList.get(i).substring(1));
}
Collections.sort(nameList);
return nameList;
}
2. Uga, yen kita nggunakake Java versi 8 lan luwih, kita mung kudu nuduhake solusi liwat stream:
public static List<String> processTheList(List<String> nameList) {
return nameList.stream()
.map(x -> x.substring(1))
.sorted().collect(Collectors.toList());
}
Preduli saka solusi sing dipilih, priksa bisa kaya ing ngisor iki:
List<String> nameList = new ArrayList();
nameList.add("John");
nameList.add("Bob");
nameList.add("Anna");
nameList.add("Dmitriy");
nameList.add("Peter");
nameList.add("David");
nameList.add("Igor");
System.out.println(processTheList(nameList));
Output konsol:
117. Muter larik
Solusi 1 Maneh, bab pisanan sing kudu dipikirake yaiku nggunakake metode Koleksi kelas sarana tambahan . Nanging amarga kita duwe array, mula kudu diowahi dadi koleksi (dhaptar):public static Integer[] reverse(Integer[] arr) {
List<Integer> list = Arrays.asList(arr);
Collections.reverse(list);
return list.toArray(arr);
}
Solusi 2 Amarga pitakonan babagan array, aku mikir yen perlu kanggo nuduhake solusi kasebut tanpa nggunakake fungsi sing wis siap metu saka kothak, lan kanggo ngomong, miturut klasik:
public static Integer[] reverse(Integer[] arr) {
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
return arr;
}
Ujian:
Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(Arrays.toString(reverse(arr)));
Output konsol:
118. Priksa manawa senar iku palindrom
Solusi 1 Iku worth langsung ngelingi StringBuilder : iku luwih fleksibel lan sugih ing macem-macem cara dibandhingake String biasa . Kita utamané kasengsem ing cara mbalikke :public static boolean isPalindrome(String string) {
string = string.toLowerCase(); //приводит всю строку к нижнему регистру
StringBuilder builder = new StringBuilder();
builder.append(string);
builder.reverse(); // перевочиваем строку методом Builder-а
return (builder.toString()).equals(string);
}
Solusi: Pendekatan sabanjure bakal tanpa nggunakake "loopholes" metu saka kothak. Kita mbandhingake karakter saka mburi senar karo karakter sing cocog saka ngarep:
public static boolean isPalindrome(String string) {
string = string.toLowerCase();
int length = string.length();
int fromBeginning = 0;
int fromEnd = length - 1;
while (fromEnd > fromBeginning) {
char forwardChar = string.charAt(fromBeginning++);
char backwardChar = string.charAt(fromEnd--);
if (forwardChar != backwardChar)
return false;
}
return true;
}
Lan kita mriksa loro pendekatan:
boolean isPalindrome = isPalindrome("Tenet");
System.out.println(isPalindrome);
Output konsol:
119. Tulis algoritma ngurutake prasaja (Gelembung, Pilihan utawa Shuttle). Kepiye carane bisa didandani?
Minangka algoritma prasaja kanggo implementasine, aku milih pilihan sort - Selection Sort:public static void selectionSorting(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j; // выбираем минимальный элемент в текущем числовом отрезке
}
}
int temp = arr[min]; // меняем местами минимальный элемент с элементом под индексом i
arr[min] = arr[i]; // так How отрезок постоянно уменьшается
arr[i] = temp; // и выпадающие из него числа будут минимальными в текущем отрезке
} // и How итог - числа оставшиеся вне текущей итерации отсортированы от самого наименьшего к большему
}
Versi sing luwih apik bakal katon kaya iki:
public static void improvedSelectionSorting(int[] arr) {
for (int i = 0, j = arr.length - 1; i < j; i++, j--) { // рассматриваемый отрезок с каждой итерацией
// будет уменьшаться с ДВУХ сторон по одному элементу
int min = arr[i];
int max = arr[i];
int minIndex = i;
int maxIndex = i;
for (int n = i; n <= j; n++) { // выбираем min и max на текущем отрезке
if (arr[n] > max) {
max = arr[n];
maxIndex = n;
} else if (arr[n] < min) {
min = arr[n];
minIndex = n;
}
}
// меняем найденный минимальный элемент с позиции с индексом min на позицию с индексом i
swap(arr, i, minIndex);
if (arr[minIndex] == max) {// срабатывает, если элемент max оказался смещен предыдущей перестановкой -
swap(arr, j, minIndex); // на старое место min, поэтому с позиции с индексом min смещаем его на позицию j
} else {
swap(arr, j, maxIndex); // простое обмен местами элементов с индексами max и j
}
}
}
static int[] swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
return arr;
}
Inggih, saiki kita kudu nggawe manawa ngurutake wis bener apik. Ayo mbandhingake kinerja:
long firstDifference = 0;
long secondDifference = 0;
long primaryTime;
int countOfApplying = 10000;
for (int i = 0; i < countOfApplying; i++) {
int[] arr1 = {234, 33, 123, 4, 5342, 76, 3, 65,
3, 5, 35, 75, 255, 4, 46, 48, 4658, 44, 22,
678, 324, 66, 151, 268, 433, 76, 372, 45, 13,
9484, 499959, 567, 774, 473, 3, 32, 865, 67, 43,
63, 332, 24, 1};
primaryTime = System.nanoTime();
selectionSorting(arr1);
firstDifference += System.nanoTime() - primaryTime;
int[] arr2 = {234, 33, 123, 4, 5342, 76, 3, 65,
3, 5, 35, 75, 255, 4, 46, 48, 4658, 44, 22,
678, 324, 66, 151, 268, 433, 76, 372, 45, 13,
9484, 499959, 567, 774, 473, 3, 32, 865, 67, 43,
63, 332, 24, 1};
primaryTime = System.nanoTime();
improvedSelectionSorting(arr2);
secondDifference += System.nanoTime() - primaryTime;
}
System.out.println(((double) firstDifference / (double) secondDifference - 1) * 100 + "%");
Loro-lorone jinis diwiwiti ing siklus sing padha, amarga yen ana puteran sing kapisah, ngurutake saka kode ing ndhuwur bakal nuduhake asil sing luwih elek tinimbang yen dilebokake nomer loro. Iki amarga kasunyatan manawa program kasebut "anget" lan banjur kerjane luwih cepet. Nanging aku arep rada metu saka topik. Sawise limang mlaku mriksa iki ing console, Aku weruh Tambah ing kinerja dening: 36.41006735635892% 51.46131097160771% 41.88918834013988% 48.091980705743566666% minangka 29.091980705743566% kanggo aku. asil cukup apik.
120. Tulis algoritma (urutan saka tumindak) kanggo nyipta literal saka tipe int karo literal saka jinis byte. Nerangake apa sing kedadeyan ing memori
-
Nilai byte diowahi dadi int. Ora 1 bait memori bakal diparengake kanggo, nanging kaya kabeh nilai int - 4, yen nilai iki durung ing tumpukan int. Yen ana, link menyang mung bakal ditampa.
-
Loro nilai int bakal ditambahake lan nomer telu bakal dipikolehi. A bagean memori anyar bakal diparengake kanggo iku - 4 bait (utawa referensi bakal ditampa saka tumpukan int kanggo Nilai ana).
Ing kasus iki, memori saka rong ints isih bakal dikuwasani, lan nilai-nilai kasebut bakal disimpen ing tumpukan int.
GO TO FULL VERSION