Tôi đang làm việc trên một ứng dụng phát nhạc.
Trong quá trình phát lại, thường thì mọi thứ cần phải xảy ra trên các luồng riêng biệt vì chúng cần xảy ra đồng thời. Ví dụ, các nốt của hợp âm cần được nghe cùng nhau, vì vậy mỗi nốt được gán một luồng riêng để chơi. (Chỉnh sửa để làm rõ: gọi note.play()
đóng băng chuỗi cho đến khi chơi nốt và đây là lý do tại sao tôi cần ba các chủ đề riêng biệt để có ba ghi chú nghe cùng một lúc.)
Loại hành vi này tạo ra nhiều chủ đề trong khi phát lại một bản nhạc.
Ví dụ, hãy xem xét một bản nhạc có giai điệu ngắn và tiến trình hợp âm ngắn đi kèm. Toàn bộ giai điệu có thể được chơi trên một chuỗi, nhưng tiến trình cần ba luồng để chơi, vì mỗi hợp âm của nó có ba nốt.
Vì vậy, mã giả để chơi một tiến trình trông như thế này:
void playProgression(Progression prog){
for(Chord chord : prog)
for(Note note : chord)
runOnNewThread( func(){ note.play(); } );
}
Vì vậy, giả sử tiến trình có 4 hợp âm và chúng tôi chơi nó hai lần, hơn là chúng tôi đang mở 3 notes * 4 chords * 2 times
= 24 luồng. Và đây chỉ là để chơi một lần.
Trên thực tế, nó hoạt động tốt trong thực tế. Tôi không nhận thấy bất kỳ độ trễ đáng chú ý nào, hoặc lỗi phát sinh từ việc này.
Nhưng tôi muốn hỏi liệu đây có phải là thực hành đúng hay không, hoặc tôi đang làm gì đó sai về cơ bản. Có hợp lý để tạo ra nhiều chủ đề mỗi khi người dùng nhấn nút không? Nếu không, làm thế nào tôi có thể làm điều đó khác nhau?
Is it reasonable to create so many threads...
phụ thuộc vào mô hình luồng của ngôn ngữ. Các luồng được sử dụng cho song song thường được xử lý ở cấp HĐH để HĐH có thể ánh xạ chúng tới nhiều lõi. Chủ đề như vậy là tốn kém để tạo và chuyển đổi giữa. Các luồng cho đồng thời (xen kẽ hai tác vụ, không nhất thiết phải thực thi đồng thời cả hai) có thể được triển khai ở cấp độ ngôn ngữ / VM và có thể được thực hiện rất "rẻ" để sản xuất và chuyển đổi giữa để bạn có thể nói, nói chuyện với 10 ổ cắm mạng ít nhiều đồng thời, nhưng bạn sẽ không nhất thiết phải có thêm thông lượng CPU theo cách đó.