Saturday, January 26, 2008

ReadWriteLock example in Java

Writing multithreaded java applications is not a piece of cake. Extra care must be taken because bad synchronization can bring your application to its knees. The JVM heap is shared by all the threads. If multiple threads need to use the same objects or static class variables concurrently, thread access to shared data must be carefuly managed. Since version 1.5, utility classes commonly useful in concurrent programming is included in the JSDK.

In Java synchronized keyword is used to acquire a exclusive lock on an object. When a thread acquires a lock of an object either for reading or writing, other threads must wait until the lock on that object is released. Think of a scenerio that there are many reader threads that reads a shared data frequently and only one writer thread that updates shared data. It's not necessary to exclusively lock access to shared data while reading because multiple read operations can be done in parallel unless there is a write operation.

In this post i'll give an example usage of ReadWriteLock interface which is introduced in the Java 1.5 API Doc. In Java Api Documentation it says :

A ReadWriteLock maintains a pair of associated locks,
one for read-only operations and one for writing.
The read lock may be held simultaneously by multiple reader threads,
so long as there are no writers. The write lock is exclusive.

Reader threads can read shared data simultaneously. A read operation does not block other read operations. This is the case when you execute an SQL SELECT statement. But write operation is exclusive. This means all readers and other writers are blocked when a writer thread holds the lock for modifing shared data.


Writer.java This class represents a thread that updates shared data. Writer uses WriteLock of ReadWriteLock to exclusively lock access to dictionary.


01 package deneme.readwritelock;
02 
03 
04 public class Writer extends Thread{
05   private boolean runForestRun = true;
06   private Dictionary dictionary = null;
07   
08   public Writer(Dictionary d, String threadName) {
09     this.dictionary = d;
10     this.setName(threadName);
11   }
12   @Override
13   public void run() {
14     while (this.runForestRun) { 
15       String [] keys = dictionary.getKeys();
16       for (String key : keys) {
17         String newValue = getNewValueFromDatastore(key);
18         //updating dictionary with WRITE LOCK
19         dictionary.set(key, newValue);
20       }
21       
22       //update every seconds
23       try {
24         Thread.sleep(1000);
25       } catch (InterruptedException e) {
26         e.printStackTrace();
27       }
28     }
29   }
30   public void stopWriter(){
31     this.runForestRun = false;
32     this.interrupt();
33   }
34   public String getNewValueFromDatastore(String key){
35     //This part is not implemented. Out of scope of this artile
36     return "newValue";
37   }
38 }



Reader.java This class represents a thread that reads share data.


01 package deneme.readwritelock;
02 
03 public class Reader extends Thread{
04   
05   private Dictionary dictionary = null;
06   public Reader(Dictionary d, String threadName) {
07     this.dictionary = d;
08     this.setName(threadName);
09   }
10   
11   private boolean runForestRun = true;
12   @Override
13   public void run() {
14     while (runForestRun) {
15       String [] keys = dictionary.getKeys();
16       for (String key : keys) {
17         //reading from dictionary with READ LOCK
18         String value = dictionary.get(key);
19         
20         //make what ever you want with the value.
21         System.out.println(key + " : " + value);
22       }
23       
24       //update every seconds
25       try {
26         Thread.sleep(1000);
27       } catch (InterruptedException e) {
28         e.printStackTrace();
29       }
30     }
31   }
32   
33   public void stopReader(){
34     this.runForestRun = false;
35     this.interrupt();
36   }
37 }



Dictionary.java This is a simple and thread safe dictionary. Read operations are managed through ReadLock and write operations (updates) are managed throuh WriteLock.


01 package deneme.readwritelock;
02 
03 import java.util.HashMap;
04 import java.util.concurrent.locks.Lock;
05 import java.util.concurrent.locks.ReentrantReadWriteLock;
06 
07 public class Dictionary {
08   
09   private final ReentrantReadWriteLock readWriteLock = 
10     new ReentrantReadWriteLock();
11 
12   private final Lock read  = readWriteLock.readLock();
13   
14   private final Lock write = readWriteLock.writeLock();
15   
16   private HashMap<String, String> dictionary = new HashMap<String, String>();
17   
18   public void set(String key, String value) {
19     write.lock();
20     try {
21       dictionary.put(key, value);
22     } finally {
23       write.unlock();
24     }
25   }
26   
27   public String get(String key) {
28     read.lock();
29     try{
30       return dictionary.get(key);
31     } finally {
32       read.unlock();
33     }
34   }
35 
36   public String[] getKeys(){
37     read.lock();
38     try{
39       String keys[] = new String[dictionary.size()];
40       return dictionary.keySet().toArray(keys);
41     } finally {
42       read.unlock();
43     }
44   }
45   
46   public static void main(String[] args) {
47     Dictionary dictionary = new Dictionary();
48     dictionary.set("java",  "object oriented");
49     dictionary.set("linux", "rulez");
50     Writer writer  = new Writer(dictionary, "Mr. Writer");
51     Reader reader1 = new Reader(dictionary ,"Mrs Reader 1");
52     Reader reader2 = new Reader(dictionary ,"Mrs Reader 2");
53     Reader reader3 = new Reader(dictionary ,"Mrs Reader 3");
54     Reader reader4 = new Reader(dictionary ,"Mrs Reader 4");
55     Reader reader5 = new Reader(dictionary ,"Mrs Reader 5");
56     writer.start();
57     reader1.start();
58     reader2.start();
59     reader3.start();
60     reader4.start();
61     reader5.start();
62   }
63   
64 }

Monday, January 21, 2008

Birkaç vi kısayolu

o : Bulunduğun satırın altına yeni bir satır açar ve yazmaya bu yeni satırdan devam edebilirsin.
w : İleriye doğru kelime kelime ilerler
b : Kelime kelime geriye gider.
cw : İmlecin üzerinde olduğu kelimeyi değiştirmeye yarar.
9G : İmleç 9. satıra gider.
H : İmleç sayfanın en tepesine gider (Birinci satıra değil görünen sayfanın ilk satırına)
L : İmleç sayfanın en altıne gider
~ : İmlecin üzerinde olduğu karakteri büyük harf ise küçük harfe, küçük harf ise büyük harfe çevirir. (case dememek için çektiğimiz sıkıntıya bak ya. Kısaca karakterin case'ini değiştirir)
. : son çalıştırılan komutu çalıştırılır.
c$ :İmlecin bulunduğu yerden satır sonuna kadar siler. Editor INSERT modunda kalır. Yazmaya devam edebiliriz.
mt : Imlecin bulunduğu satırı "t" etiketi ile işaretler 't ile imleç işaretli satıra uçar.

vi editörü ile ilgili daha detaylı türkçe bilgi için belgeler.org adresine bakabilirsiniz.

Friday, January 18, 2008

Başkaldıran dosya sistemlerini fuser ile hizaya getirin

Önce bu fuser da nedir diyenler için kısa bir açıklama:

Dosya sistemindeki bir dosyayı ya da bir soketi hangi
process'in kullandığını gösteren komut.

"Tamam da ne işime yarayacak dosyayı hangi process'in kullandığını öğrenmek" diyenler için de fuser kullanımı ile ilgili bir örnek verelim. Yeni yazdığınız bir CD'yi CD sürücünüze takıp mount ettiniz. CD içindeki dokumanlarla işiniz bittikten sonra CD'yi çıkartmaya çalıştığınızda aşağıdaki gibi bir mesajla karşılaşabilirsiniz:



Ya da komut satırında umount komutu ile CD'yi unmount etmek isteğinizde aşağıdaki gibi "device is busy" mesajı ile karşılaşabilirsiniz.



İşte fuser tam burada yardıma koşuyor. CD'yi meşgul eden process'in PID'sini bulmak için aşağıdaki işlemler yapılır.



Bizim örneğimizde aranan process 7614 numaralı evince dir.(Gnome Document Viewer) Bu process'i kapattıktan sonra CD yi problemsiz unmount edebiliriz.

Kullandığım firefox eklentileri


  1. del.icio.us buttons.
    İnternette surf yaparken beğendiğim sayfaları del.icio.us profilime eklemek için kullanıyorum. http://del.icio.us/ilkinulas

  2. AdBlockPlus
    Olmazsa olmaz bir plugin.

  3. Tab Mix Plus
    Firefox'un tab özelliğine ilave özellikler ekliyor. Yanlışlıkla kapattığınız bir tab'ı yeniden açmak gibi.

  4. Web Developer Plugin
    Özellikleri saymakla bitmez. Web'de geliştirme yapıyorsanız çok işinize yaracak bir plugin. En beğendiğim özellikleri:
    cookie arayüzü ve sayfa içindeki bütün HTML elemanlarını açıp kapayabilme özelliği.

  5. Firebug
    Özellikle Ajax ile geliştirme yapanlar için çok kullanışlı bir plugin. Firefox'un asenkron yaptığı HTTP request'leri firebug console'dan takip edebilirsiniz.

  6. UnPlug
    Bu plugin'i Youtube videolarını bilgisayarınıza indirmek için kullanabilirsiniz.

  7. YSlow
    Firebug plugin'ine ek olarak kullanılan bu plugin'i Yahoo geliştirmiş. We sayfasını yahoo'nun belirlediği kriterlere göre sınıyor. Bir nevi performans testi uyguluyor.

  8. Greasemonkey
    Bu plugin kısaca, sayfa yüklendikten sonra sayfada post-processing yaparak sayfanın yeniden yapılandırılmasını sağlar. Sadece greasemonkey plugin'ini kurmak yetmez. Greasemonkey sitesinden "user script" denen betikleri kurmanız gerekmektedir.

Sunday, January 13, 2008

A Tutorial on XML Namespaces


XML namespaces are used to avoid element name conflicts. A namespace is a set of names in which all names are unique. An XML namespace can be tought as a Java package name. To distinguish two classes of the same name we put the classes in two different packages. For example; you may choose to put a class that is used to connect to a relational database system in com.foo.sql package (com.foo.sql.Connection) and a class that manages TCP/IP socket connections in com.foo.net package (com.foo.net.Connection).

An XML namespace is used in the same way. Namespaces make it easier to come up with unique names. Without namespaces all XML element names must be unique all over the world. I'll try to explain this with an example.

Xml representation of a java class.

<class>
<name>com.foo.bar.Customer</name>
<method>getName</method>
<method>setName</method>
<superclass>com.foo.bar.Person</superclass>
</class>

Xml representation of a college class.

<class>
<code>MATH101E</code>
<name>Mathematics 1</name>
<language>English</language>
<credits>4</credits>
<class>

If these two "class" XML elements are used in the same XML document there will a name conflict. These name conflicts can be resolved by using namespaces.

<j:class xmlns:j="http://java.sun.com/class">
<j:name>com.foo.bar.Customer</j:name>
<j:method>getName</j:method>
<j:method>setName</j:method>
<j:superclass>com.foo.bar.Person</j:superclass>
</j:class>

<itu:class xmlns:itu="http://java.sun.com/class">
<itu:code>MATH101E</itu:code>
<itu:name>Mathematics 1</itu:name>
<itu:language>English</itu:language>
<itu:credits>4</itu:credits>
</itu:class>

ITU : Istanbul Technical University

XML namespaces are defined with XML Namespace (xmlns) Attribute. The XML namespace attribute is placed in the start tag of an element and has the following syntax:

xmlns:namespace-prefix="namespaceURI"

When a namespace is defined in the start tag of an element, all child elements with the same prefix are associated with the same namespace.
If this tutorial is not enough for you can read these articles:
  • Xml namespaces from w3schools
  • Understanding XML Namespaces from Micro$oft MSDN library
  • XML Namespaces by Example from xml.com
  • Xml namespaces from wikipedia
  • XML Schema: Understanding Namespaces from Oracle

  • Thursday, December 6, 2007

    Kill A Process By Name

    My favorite shell command is kill. Don't worry I'm not a serial killer.
    If you know the process id and if you have enough permissions you can kill any process you want . It is easier to kill a process by name. Here is the command.

    kill -9 `ps -ef | grep $1 | grep -v grep | awk '{print $2}'`


    kill -9 processId sends SIGKILL signal to specified process. You can use a list of process ids as kill command argument. kill -9 pid1 pid2 pid3
  • ps -ef|grep $1
    Lists process that matches $1
  • ps -ef | grep $1 | grep -v grep
    List process that matches $1 except the process that runs grep command
  • ps -ef | grep $1 | grep -v grep | awk '{print $2}
    Lists only process ids of processes that matches $1 except the process that runs grep command.

    awk '{print $2}' lists the second column of the
    ps -ef | grep $1 | grep -v grep 
    command output.

    Save kill -9 `ps -ef | grep $1 | grep -v grep | awk '{print $2}'` in a file called myKill.sh
    Give execute permission to the myKill.sh file (chmod +x myKill.sh)
    If you want to kill all java processes type
    ./myKill.sh java
    Or you can use pgrep and pkill commands if they are available on your system.
  • Tuesday, December 4, 2007

    Watch multiple log files with "tail"

    Log files are the first place i look while debugging an application. To see the logs in real-time I am using the utility command "tail" with the "-f" option.

    tail -f filename

    When there are multiple log files to watch out, I used to open different xterm console to tail each file.But today I learned that "tail" can watch multiple files for changes. Example command and its output on my PC (Ubuntu 7.10).


    tail -f logs/catalina.out InaWs.log InaWsUserActions.log

    ==> logs/catalina.out <==
    [2007-12-04 09:39:18,746] INFO(ContextManager.java.initialize:56) - Context [vpn] initialized.
    [2007-12-04 09:39:18,760] INFO(ContextManager.java.initialize:56) - Context [prepaid] initialized.
    [2007-12-04 09:39:18,761] INFO(InaWsImpl.java.initialize:116) - Using auhentication factory : com.oksijen.inox.common.ws.auth.PlaintextAuthenticationFactory
    Dec 4, 2007 9:39:19 AM com.sun.xml.ws.transport.http.servlet.WSServletDelegate
    INFO: WSSERVLET14: JAX-WS servlet initializing

    ==> InaWs.log <==
    [2007-12-04 09:39:18,743] INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (InaWsContext.java.addAction:41) - Adding action. actionName[echoVpn]...
    [2007-12-04 09:39:18,744] INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (C3p0Impl.java.initialize:53) - Initializing C3P0 connection pool....
    [2007-12-04 09:39:18,757] INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (InaWsContext.java.addAction:41) - Adding action. actionName[echoPrepaid]...
    [2007-12-04 09:39:18,758] INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (C3p0Impl.java.initialize:53) - Initializing C3P0 connection pool....

    ==> InaWsUserActions.log <==
    20071204093501054 REQ 117787e671a35c5c03e072efbd53bad3cea0ae49 root prepaid echoPrepaid [test]
    20071204093501054 RES 117787e671a35c5c03e072efbd53bad3cea0ae49 1
    20071204093520876 REQ 117787e671a35c5c03e072efbd53bad3cea0ae49 root vpn echoVpn [test]
    20071204093520876 RES 117787e671a35c5c03e072efbd53bad3cea0ae49 1
    20071204093530380 REQ 117787e671a35c5c03e072efbd53bad3cea0ae49 root mpbx echoMpbx []
    20071204093546634 REQ 117787e671a35c5c03e072efbd53bad3cea0ae49 root mpbx listAgents []
    20071204093549223 RES 117787e671a35c5c03e072efbd53bad3cea0ae49 100101