Bildiğiniz gibi biz programlarımızı farklı işlemleribağımsız olarak yürütülecek şekilde tasarlıyabiliyoruz. Bu işlemleri ayrı kanallarda yaparken grafik arayüz ile ilgilenmeye başlayınca aklımıza kullanıcı arayüzünün de performans açısından çok kanallı tasarlanabilineceği aklımıza gelmiş olabilir. Ancak gerçekte çoğu çizim işlemi ve olay yönetimi tek kanalda yapılacak şekilde dizayn edilir.
Not: Swing içerisinde her zaman tek kanallık söz konusu olmaya bilir. Bazı çalışma zamanı ortamlarında çok kanallı yaklaşım sergilenebilir. Ayrıca Swing dökümanları içerisinde Thread-Safe ifadeleri yer alabilir. Thread-Safe ile işaret edilen durumlar java tarafından sekronize edilmiştir ve aşağıda bahsedeceğim çizim hatalarına neden olmaz.
Bunun asıl sebebi çok kanallı yaklaşımın hem hataları ayıklamayı zorlaştırmaları hemde bazı garip davranışlara yol açması. Bazı sistemler kanalları belirli bir süre çalıştırıp durdururken bazıları ise kanalın kendi isteği ile işlemciyi serbest bırakmasını destekler. Bu iki durumdan bir sakıncası var. Bildiğiniz gibi bir kanal bir iş yaparken yaptığı iş yarıda kesilebilir. Bu durumda o iş yarıda kalır. Yapılan bu iş sonucu bir çizim yapılacaksa mesela bir düğmenin etiketi çizilecekse o etiket şaçma sapan çizilebiliyor. Çünkü etiketin içeriğini değiştiren kod parçası işini bitiremeden durdurulmuş ve çizim kanalı çalıştırılmıştır. İşte tüm bu ve burada açıklanmayan bazı durumlardan dolayı kullanıcı arayüzünü ilgilendiren bütün işlemler aynı kanalda yapılır. İşte bu kanalın adı EDT dir.
Arayüzü değiştirme işlerinin hepsi EDT içerisinde yapılması gereklidir. EDT için yapılan çağrılar her zaman bir kuyruğa sokulur. Arka arkaya yapılan bir çok çağrı birleştirilip tek sefer de işlenebilir yada sırayla işlenir. İşleri bu şekilde yapamnın bir yararıda kullanıcı arayüzünüzün donmasını engellemektir.
Swing EDT için bazı metotlar sağlar. Bu metotlar:
static void invokeLater(Runnable r) static void invokeAndWait(Runnable r) static boolean isEventDispatchThread()invokeLater Desktop uygulamalarında invokeAndWait Applet uygulamalarında kullanılır. Aslında iki metotda java.awt.EventQueue sınıfındaki metotların tetikleyen cover metotlardır.
invokeLater asenkron olarak çalıştırılırken invokeAndWait senkron olarak çalışır. invokeAndWait illa appletler için kullanılacak diye bir şey yok ancak arayüzü ilk yapılandırırken appletlarda kullanılması önerilmektedir. invokeAndWait AWT kanalı işlem bitene kadar beklemeye alır.
invokeLater'ın önemi uzun hesaplamalar yapacağımız zaman ya da network'e bağlantı yapıp bir veritabanından veri çekeceğimiz zaman ortaya çıkar. Eğer bu işlemleri AWT-Thread (Event Dispatch Thread) içinde yaparsak ve kullanıcı pencereyi ikon durumuna getirip tekrar ekrana büyütürse pencere içerisinin boyanmadığını doğal olarak programın donduğu gibi bir imaj oluştuğunu görürsünüz.
Peki içerisinde bulunduğumuz kanalın AWT kanalı olup olmadığını nasıl anlarız. isEventDispatchThread metodu true gönderirse bu AWT kanalı içerisinde olduğumuzu gösterir. False değeri ise tersini ispatlar.
Swing kütüphanesi tüm bu zorluklardan standart ve kolay bir yöntemle kurtulmamız için SwingWorker adında JavaSE6 (JDK 1.6 / JRE1.6) ile gelen sınıfı bünyesine dahil etmiştir. Ayrıca bu yazının yazıldığı tarih itibari ile terkedilmiş bir çatı olan SAF (Swing Application Framework) Task ile daha iyi çözümler üretmiştir. SAF'ın akıbetinden sonra onun halefi olan BSAF(Better Swing Application Framework) ortaya çıkmıştır. BSAF'ı google dan aratmanızı tavsiye ederim. Çünkü bu yazı yazılırken kenai üzerinde konumlanan BSAF java.net'e henüz geçmemişti. Swing Worker SAF ve BSAF başka bir yazının konusu. Şimdilik Swing ve EDT konusu bu kadar. Aklıma başka bir şeyler gelirse bu yazıyı güncelleyebilirim yada Swing ve EDT (2) şeklinde başka bir başlıkta yayınlayabilirim.
Not: Kenai Oracle kararı ile özellikleri java.net'e aktarılacak ve Oracle'ın kendi içerisinde geliştirilen yazılımlara ev sahipliği yapacak ve son olarak dışarıya kapatılacaktı. Kenai üzerinde konuşlanan yazılım depoları otomatikman java.net'e aktarılacaktı.