You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Lesson_12/README.MD
+193-1Lines changed: 193 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -93,4 +93,196 @@ pub fn multi_producer() {
93
93
}
94
94
```
95
95
96
-
Bu örnekte 10 farklı **thread** kanala mesaj bırakır. Thread'ler **spawn** çağırısı ile ayağa kaldırılmadan önce **transmitter** nesnesinin bir klonunun oluşturulduğunda dikkat edilmelidir. Her bir **thread** kendi **transmitter** klonunu kullanarak kanala mesaj bırakır. Mesajlar kanala senkron sırada bırakılır. İlerleyen satırlarda bir **for** döngüsü ile kanala gelen mesajların **Receiver** nesnesi üzerinden yakalanması işlemi gerçekleştirilir. Dikkat edilmesi gereken noktalardan birisi de **drop** çağrısıdır. Açık bir şekilde **transmitter** nesnesi açıkça **drop** edilmiştir. Bu yapılmadığı durumda receiver dan mesajlar dinlenmeye devam eder ve program sonlanmaz. Bu bazı durumlarda zaten istenen bir durumdur. Sürekli dinlemede kalması gereken bir receiver gerektiren senaryolar buna örnek verilebilir.
96
+
Bu örnekte 10 farklı **thread** kanala mesaj bırakır. Thread'ler **spawn** çağırısı ile ayağa kaldırılmadan önce **transmitter** nesnesinin bir klonunun oluşturulduğunda dikkat edilmelidir. Her bir **thread** kendi **transmitter** klonunu kullanarak kanala mesaj bırakır. Mesajlar kanala senkron sırada bırakılır. İlerleyen satırlarda bir **for** döngüsü ile kanala gelen mesajların **Receiver** nesnesi üzerinden yakalanması işlemi gerçekleştirilir. Dikkat edilmesi gereken noktalardan birisi de **drop** çağrısıdır. Açık bir şekilde **transmitter** nesnesi açıkça **drop** edilmiştir. Bu yapılmadığı durumda receiver dan mesajlar dinlenmeye devam eder ve program sonlanmaz. Zire klonlanan receiver örnekler halen daha yaşamaktadır. Bazı durumlarda zaten istenen bir durumdur. Sürekli dinlemede kalması gereken bir receiver gerektiren senaryolar buna örnek verilebilir. Farklı bir örnekle devam edip otomatik kapanma durumunu ele alalım.
Bu örnekte transmitter ve transmitter_clone nesneleri tanımlandıkları thread'ler sonlandığında düşürülürler ve dolayısıyla receiver üzerinden yakalanacak kanal mesajlarının sayısı bellidir. Dolayısıyla program beklendiği şekilde tüm kanal mesajları işlendikten sonra sonlanır.
131
+
132
+
## Örnek Senaryo
133
+
134
+
Kanal kullanımları ile ilgili örnek bir senaryo ele alalım. Bu senaryoda sistemdeki n sayıda rapor dosyasının n thread ile işlenmesi söz konusudur. Her bir thread ele aldığı dosyayı işledikten sonra kanal üzerine bilgi bırakır. En sonunda tüm bu bilgiler receiver üzerinden toplanır. İlk versiyonda standart kütüphanenin Sender ve Receiver yapıları kullanılmaktadır.
// Rapor dosyalarının işlendiği bazı business'lar çağırdığımızı düşünelim
167
+
168
+
thread::sleep(Duration::from_secs(sleep_time));
169
+
170
+
transmitter
171
+
.send(format!(
172
+
"Finished processing '{}' in {} seconds",
173
+
report, sleep_time
174
+
))
175
+
.unwrap();
176
+
});
177
+
}
178
+
179
+
drop(transmitter);
180
+
println!("Started the processing reports");
181
+
forresultinreceiver {
182
+
println!("Status {}", result);
183
+
}
184
+
println!("Completed the processing reports");
185
+
}
186
+
```
187
+
188
+
Her dosya sıralı bir şekilde döngüye girer ve herbirisi için ayrı bir **thread** açılır. Bu thread'lerde dosyalar ile ilgili farklı iş süreçlerinin işletildiğini düşünebiliriz. Dosya işleyişlerinin farklı sürelerde gerçekleştiğini simüle etmek için rand kütüphanesi ile üretilen rastgele değerlerde beklemeler yapılmaktadır.
189
+
190
+
## Asenkronluk
191
+
192
+
Rust'ın MPSC modülü aslında gerçek anlamda bir asenkronluk sağlamaz. Bir başka deyişle Sender'dan mesajlar asenkron olarak ilerletilebilse de Receiver tarafı bunları senkron olarak işler. Tam bir asenkron çalışma sağlayabilmek için yardımcı küfelerden _(crates)_ yararlanılabilir. Aşağıdaki ilk senaryoda ana thread'in bloklanmasına neden olan bir döngü kullanımı söz konusudur.
// Aşağıdaki döngü main thread üzerine çalışıp buradaki akışı bloklamaya neden olacak
219
+
foriin0..10 {
220
+
thread::sleep(Duration::from_secs(1));
221
+
println!("Main task is working...Counting {}", i);
222
+
}
223
+
224
+
whileletOk(message) =receiver.recv() {
225
+
println!("{}", message);
226
+
}
227
+
228
+
println!("All tasks completed!");
229
+
}
230
+
```
231
+
232
+
// ÇALIŞMA ZAMANI GÖRÜNTÜSÜ EKLENECEK
233
+
234
+
Aynı örneği **tokio** küfesini kullanarak ele aldığımızda ise ana thread'in bloklanmadan for döngüsünün işletildiğini görebiliriz. Bu receiver tarafında mesajların asenkron ele alınabildiğinin de ispatıdır. tokio küfesini kullanmak için **Full feature** seti ile eklenmesi gerekmektedir.
235
+
236
+
```bash
237
+
cargo add tokio -F full
238
+
```
239
+
240
+
Örnek kod;
241
+
242
+
```rust
243
+
usestd::time::Duration;
244
+
usetokio::sync::mpsc;
245
+
246
+
#[tokio::main]
247
+
pubasyncfnmain() {
248
+
do_with_tokio().await;
249
+
}
250
+
251
+
pubasyncfndo_with_tokio() {
252
+
let (transmitter, mutreceiver) =mpsc::channel(10);
253
+
254
+
foriin1..=5 {
255
+
lettx_clone=transmitter.clone();
256
+
tokio::spawn(asyncmove {
257
+
tokio::time::sleep(Duration::from_secs(5)).await;
258
+
tx_clone
259
+
.send(format!("Task {} completed", i))
260
+
.await
261
+
.unwrap();
262
+
});
263
+
}
264
+
265
+
drop(transmitter);
266
+
267
+
println!("Waiting for all tasks...");
268
+
269
+
/*
270
+
Standart mpsc örneğinden farklı olarak burada ana thread bloklanmadan
271
+
döngünün asenkron olarak çalıştırılması sağlanır.
272
+
*/
273
+
tokio::spawn(async {
274
+
foriin0..10 {
275
+
tokio::time::sleep(Duration::from_secs(1)).await;
276
+
println!("Main task is working...Counting {}", i);
0 commit comments