Rangkaian penjadwalan
Setiap rangkaian memiliki prioritas rangkaian yang ditetapkan untuk itu. Rangkaian yang dibuat dalam runtime bahasa umum awalnya diberi prioritas ThreadPriority.Normal. Rangkaian yang dibuat di luar runtime mempertahankan prioritas yang mereka miliki sebelum memasuki lingkungan terkelola. Anda bisa mendapatkan atau mengatur prioritas rangkaian apa pun dengan properti Thread.Priority.
Rangkaian dijadwalkan untuk eksekusi berdasarkan prioritas mereka. Meskipun rangkaian sedang dijalankan dalam runtime, semua rangkaian diberi potongan waktu prosesor oleh sistem operasi. Detail algoritma penjadwalan yang digunakan untuk menentukan urutan di mana utas dijalankan bervariasi menurut setiap sistem operasi. Di bawah beberapa sistem operasi, rangkaian dengan prioritas tertinggi (dari rangkaian yang dapat dieksekusi) selalu dijadwalkan untuk berjalan terlebih dahulu. Jika beberapa rangkaian dengan prioritas yang sama semuanya tersedia, penjadwal siklus melalui rangkaian pada prioritas itu, memberikan setiap thread potongan waktu tetap di mana untuk menjalankan. Selama rangkaian dengan prioritas yang lebih tinggi tersedia untuk dijalankan, rangkaian prioritas yang lebih rendah tidak dapat dijalankan. Ketika tidak ada lagi rangkaian yang dapat dijalankan pada prioritas tertentu, penjadwal pindah ke prioritas yang lebih rendah berikutnya dan menjadwalkan rangkaian pada prioritas itu untuk pengeksekusian. Jika rangkaian prioritas yang lebih tinggi menjadi dapat dijalankan, rangkaian prioritas yang lebih rendah akan didahului dan utas prioritas yang lebih tinggi diizinkan untuk dijalankan sekali lagi. Di atas semua itu, sistem operasi juga dapat menyesuaikan prioritas rangkaian secara dinamis karena antarmuka pengguna aplikasi dipindahkan antara latar depan dan latar belakang. Sistem operasi lain mungkin memilih untuk menggunakan algoritma penjadwalan yang berbeda.
Contoh
Berikut adalah contoh eksekusi 9 utas di semua 5 tingkat prioritas dari Thread.Priority enumerasi di mana 5 terakhir berada pada tingkat prioritas tertinggi. Selain itu, kami memiliki dukungan panggilan balik dari artikel sebelumnya yang dalam konteks ini menunjukkan bahwa urutan inisialisasi dan prioritas utas mungkin tidak selalu tercermin dalam kode berikutnya atau eksekusi proses memulai urutan. Artinya, kita melihat di sini sifat paralel dari eksekusi kode dan demonstrasi irisan waktu prosesor yang ditetapkan oleh sistem operasi untuk setiap utas. Ini menyoroti pengaruh dan kontrol lingkungan tempat utas berjalan. Dengan itu, kita tentu melihat bahwa utas prioritas tertinggi memang menerima prioritas dalam eksekusi.
Kode berikut akan menghasilkan hasil arbitrer pada setiap eksekusi. Namun, pola urutan umum prioritas yang dijalankan dapat diamati setelah menjalankan kode beberapa kali dan menganalisis output.
namespace snippets;
public class SchedulingThreads
{
public void RunMultipleThreadsOnDifferentPriorities()
{
var threadsList = new List<Thread>(9);
// Initialize 9 threads. 5 with Highest priority, and the first 4 from Lowest to Normal range.
for (int i = 0; i < 9; i++)
{
var thread = new Thread(() => { new ThreadWithCallback(Callback).Process(); });
if (i > 3)
thread.Priority = ThreadPriority.Highest;
else
thread.Priority = (ThreadPriority)i;
threadsList.Add(thread);
}
threadsList.ForEach(thread => thread.Start());
}
public void Callback(ThreadPriority threadPriority)
{
Console.WriteLine($"Callback in {threadPriority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
}
public class ThreadWithCallback
{
public ThreadWithCallback(Action<ThreadPriority> callback)
{
this.callback = callback;
}
public Action<ThreadPriority> callback;
public void Process()
{
Console.WriteLine($"Entered process in {Thread.CurrentThread.Priority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
Thread.Sleep(1000);
Console.WriteLine($"Finished process in {Thread.CurrentThread.Priority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
if (callback != null)
{
callback(Thread.CurrentThread.Priority);
}
}
}
// The example displays the output like the following:
// Entered process in Highest priority. ThreadId: 9.
// Entered process in Highest priority. ThreadId: 12.
// Entered process in Normal priority. ThreadId: 6.
// Entered process in BelowNormal priority. ThreadId: 5.
// Entered process in Lowest priority. ThreadId: 4.
// Entered process in AboveNormal priority. ThreadId: 7.
// Entered process in Highest priority. ThreadId: 11.
// Entered process in Highest priority. ThreadId: 10.
// Entered process in Highest priority. ThreadId: 8.
// Finished process in Highest priority. ThreadId: 9.
// Finished process in Highest priority. ThreadId: 12.
// Finished process in Highest priority. ThreadId: 8.
// Finished process in Highest priority. ThreadId: 10.
// Callback in Highest priority. ThreadId: 10.
// Finished process in AboveNormal priority. ThreadId: 7.
// Callback in AboveNormal priority. ThreadId: 7.
// Finished process in Lowest priority. ThreadId: 4.
// Callback in Lowest priority. ThreadId: 4.
// Finished process in Normal priority. ThreadId: 6.
// Callback in Highest priority. ThreadId: 9.
// Callback in Highest priority. ThreadId: 8.
// Callback in Highest priority. ThreadId: 12.
// Finished process in Highest priority. ThreadId: 11.
// Callback in Highest priority. ThreadId: 11.
// Callback in Normal priority. ThreadId: 6.
// Finished process in BelowNormal priority. ThreadId: 5.
// Callback in BelowNormal priority. ThreadId: 5.
}