29 Kasım 2017 Çarşamba

Selector Sınıfı - NIO

Giriş
Şu satırı dahil ederiz.
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
Kullanım
Genellikle bu sınıfı süren yani select() metodunu çağıran 1 veya daha fazla thread bulunur.

Bu sınıfa verilen socket nesnelerinin non-blocking olması gerekir. Yani şöyle yaparız.
ServerSocketChannel serverChannel = ...;
serverChannel.configureBlocking(false);
Channel'dan SelectionKey'e erişmek için şöyle yaparız.
SocketChannel channel = ...;
SelectionKey key = channel.keyFor (selector);
Örnek
NIO Server için şöyle yaparız. Burada selectedKeys().iterator() şeklinde kullanılıyor ama gereksiz. Direkt selectedKeys() üzerinde for döngüsü kurmak daha iyi.
Selector selector = Selector.open(); // Open a selector
// Open a server socket channel
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress(8080));
serverSocket.configureBlocking(false);
// Register the server socket channel with the selector
serverSocket.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
  // Wait for events
  selector.select();
  // Iterate over the events
  Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
  while (iterator.hasNext()) {
    SelectionKey key = iterator.next();
    // Handle a new connection
    if (key.isAcceptable()) {
      ServerSocketChannel channel = (ServerSocketChannel) key.channel();
      SocketChannel client = channel.accept();
      client.configureBlocking(false);
      client.register(selector, SelectionKey.OP_READ);
    }
    // Handle a read event
    if (key.isReadable()) {
      SocketChannel client = (SocketChannel) key.channel();
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      int read = client.read(buffer);
      if (read > 0) {
        buffer.flip();
        String message = new String(buffer.array(), 0, read);
      }
    }
    iterator.remove();
  }
}
close metodu
Örnek ver

keys metodu
Açıklaması şöyle
"Returns this selector's key set. The key set is not directly modifiable. A key is removed only after it has been cancelled and its channel has been deregistered. Any attempt to modify the key set will cause an UnsupportedOperationException to be thrown. The key set is not thread-safe."
open metodu
Şöyle yaparız.
Selector selector = Selector.open();
select metodu
Genelde bir döngü için şöyle kullanılır. "Ready" olan key sayısını döner. 

Örnek
Şöyle yaparız.
while (true) {
  selector.select();

  Set<SelectionKey> keys = selector.selectedKeys();
  for (SelectionKey key : keys) {
    SelectableChannel channel = key.channel();

    if (key.isAcceptable())    {...}
    else if (key.isWritable()) {...}
    else if (key.isReadable()) {...}
    }   
}
selectedKeys metodu
Açıklaması şöyle. selectedKey() her zaman keys() metodunun alt kümesini döndürür.
"Returns this selector's key set. The key set is not directly modifiable. A key is removed only after it has been cancelled and its channel has been deregistered. Any attempt to modify the key set will cause an UnsupportedOperationException to be thrown. The key set is not thread-safe."
Şöyle yaparız. key'ler ile ilgili yapılabilecek işlemker için SelectionKey Sınıfı'na bakınız.
Set readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();  
while (it.hasNext()) {
  SelectionKey key = (SelectionKey )it.next();
  if (key.isReadable()) {
    ...
  }
  it.remove();
}
Döngüdeki remove() çağrısıının açıklaması şöyle
Notice the keyIterator.remove() call at the end of each iteration. The Selector does not remove the SelectionKey instances from the selected key set itself. You have to do this, when you are done processing the channel. The next time the channel becomes "ready" the Selector will add it to the selected key set again.
selectNow metoud
Şöyle yaparız.
Selector selector = ...;

if (selector.selectNow() != 0) {
  ...
}
wakeUp metodu
Selector select() metodu içinde bloke olmuş iken yeni bir SelectableChannel eklenirse,kapatılırsa vs. select() çağrısından çıkarmak için kullanılır.
Örnek ver

Diğer
Gördüğüm bir gerçekleştirimde bu sınıf sarmalanıyordu. Okuma ve yazma işlemi için kuyruklar tutuluyordu.
Map <SocketChannel ,Queue <ByteBuffer>> outgoingData = ...;
ByteBuffer incomingData =...
Gönderilecek veri kuyrupa ekleniyor ve channel için SelectionKey.OP_WRITE işlemi başlatılıyor.
Socket müsait olunca yazma işlemi başlıyor ve tüm veri döngü içinde gönderilmeye çalışılıyor. Yazma işlemi bitince map boş ise SelectionKey.OP_READ başlatılıyor.

Okuma işleminde incomingData temizleniyor ve okuma işlemi yapılıyor. Bu veri daha sonra hemen bir işlenmek üzere bir kuyruğa konuluyor. Kuyruk şöyle
BlockingQueue<NetworkEvent > eventQueue = ...;




22 Kasım 2017 Çarşamba

Swing JMenuBar Sınfı

Giriş
Şu satırı dahil ederiz.
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
Bu sınıf bir JFrame nesnesine menü eklemek içindir.

Örnek
Elimizde bir frame olsun. Şöyle yaparız.
setJMenuBar(new MyMenuBar());
MenuBar şöyledir.
class MyMenuBar extends JMenuBar implements ActionListener{
  public static JMenuItem itmOpen;

  public MyMenuBar() {
    JMenu menuFile = new JMenu("File");

    itmOpen = new JMenuItem("Open...");
    itmOpen.addActionListener(this);

    add(menuFile);
    menuFile.add(itmOpen);
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    JMenuItem source = (JMenuItem)e.getSource();

    if(source == itmOpen){
      ...
    }
  }
}
constructor
Şöyle yaparız..
JMenuBar menuBar = new JMenuBar ();
add metodu
Şöyle yaparız..
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);