월별 글 목록: 2009년 6월월

sjava-config 1.0

설정파일을 저장하고 가져오는 라이브러리입니다.
sjava-config는 http://www.jconfig.org/jconfig를 보고 필요한 형태(xml만 지원)로만 개발했습니다.
여러형태의 설정파일을 읽어올 수 있도록 common한 기능은 추상 클래스로 빼고 설정을 읽는 코드는 하위 클래스에서 구현을 합니다.

설정파일의 형태는 아래와 같습니다.
sjava-config.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<sjava-config>
    <!– array variable delimeter is “,” –>
    <!– sjava-config 설정, 아래 설정은 지우지 마세요 –>
    <sjava-service name=”config”>
        <key name=”watch” value=”true” /> <!– true, false –>
        <key name=”interval” value=”60″ /> <!– 60 seconds –>
    </sjava-service>
   
    <!– 로그서버 설정 –>
    <sjava-service name=”log”>
        <key name=”host” value=”111.111.111.111,222.222.222.222″ />
        <key name=”port” value=”20003″ />
    </sjava-service>
</sjava-config>

그리고 위 파일(sjava-config.xml)은 classpath에 위치를 해야 읽을 수 있습니다.

ConfigTest.java

package net.sjava.config.demo;

import net.sjava.config.ConfigHandler;

/**
 * Code Coverage Test Class using EclEmma
 * @author mcsong@gmail.com
 * @since 2009. 6. 29.
 */
public class ConfigTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
       
        ConfigHandler configHandler = ConfigHandler.getInstance();
        System.out.println(configHandler.isLoading() ? “loading true” : “loading fail”);
       
        System.out.println(“- get vlaue test —“);
        System.out.println(configHandler.getValue(“config”, “watch”));
        System.out.println(configHandler.getValue(“config”, “interval”));
        System.out.println(configHandler.getValue(“log”, “host”));
        System.out.println(configHandler.getValue(“log”, “port”));
        System.out.println(configHandler.getValue(“auth”, “host”));
        System.out.println(configHandler.getValue(“auth”, “port”));
       
        System.out.println(“- default value test —“);
        System.out.println(configHandler.getValue(“config”, “watch”, “false”));
        System.out.println(configHandler.getValue(“config”, “interval”, “11”));
        System.out.println(configHandler.getValue(“log”, “host”, “222.222.222.222”));
        System.out.println(configHandler.getValue(“log”, “port”, “20003”));
        System.out.println(configHandler.getValue(“auth”, “host”, “222.222.222.222”));
       
        System.out.println(“- array value test —“);
        for(int i = 0; i < configHandler.getValues(“log”, “host”).length; i++) {
            System.out.println(configHandler.getValues(“log”, “host”)[i].toString());
        }
       
        for(int i = 0; i < configHandler.getValues(“auth”, “host”).length; i++) {
            System.out.println(configHandler.getValues(“auth”, “host”)[i].toString());
        }
       
        System.out.println(“- add value —“);
        configHandler.addValue(“test”, “host”, “1.1.1.1”);
        System.out.println(configHandler.getValue(“test”, “host”));
       
        System.out.println(“- modify value —“);
        configHandler.setValue(“test”, “host”, “2.2.2.2”);
        System.out.println(configHandler.getValue(“test”, “host”));
       
        System.out.println(“- modify values —“);
        String[] values = {“2.2.2.2”, “3.3.3.3”};
        configHandler.setValues(“test”, “host”, values);
       
        for(int i = 0; i < configHandler.getValues(“test”, “host”).length; i++) {
            System.out.println(configHandler.getValues(“test”, “host”)[i].toString());
        }
    }

}

바이너리

cfile22.uf.192608224A496BF83C2426.zip소스
cfile24.uf.182D46214A496C836B36DA.zip

리액터(Reactor) 패턴의 성능 향상 방안..

리액터(Reactor) 패턴을 사용해서 자바 네트워크 서버를 개발하다 보면, 동접을 2000 이상 붙여보면 성능저하를 확인할 수 있다. 그래서 리액터를 마스터-슬레이브(Master-Slave)의 구조로 개선하고, 슬레이브 리액터의 개수를 CPU 개수만큼 만들어서 성능을 개선할 수 있다. 아래는 이 구조를 쉽게 알수 있는 그림이다.^^

DI(Dependency Injection)에 대해서..

객체가 스스로 참조하는 객체를 생성하지 않고, 외부 환경(컨테이너)에서 삽입 되는 형태를 DI(Dependency Injection)라고 한다. 그리고, DI를 구현하는 방법은 2가지가 있다.

1. 생성자(Constructor) 방식

public class Shop {   
  private final StockManager stockManager;   
  private final String shopZipCode;   
  public Shop(StockManager stockManager, String shopZipCode) {   
       this.stockManager = stockManager;   
       this.shopZipCode = shopZipCode;   
  }   
}

2. 세터(Setter) 방식

public class Shop {   
  StockManager stockManager;   
  String shopZipCode;   
  /**  
  * @service name="StockManager"       
  */  
  public void setStockManager(StockManager stockManager) {   
      this.stockManager = stockManager;   
  }   
  /**  
  * @config name="shopZipCode"       
  */  
  public void setStockManager(String shopZipCode) {   
      this.shopZipCode= shopZipCode;   
  }   
  // TODO - Joe - how does setter injector do config ? Same way?   
  public void initialize() {   
      // all setXXXs are now done  
  }   
} 

문자열 비교 안전하게 하기

문자열을 비교하는 코드는 프로그램을 개발하다보면 많이 사용하게 됩니다.
보통 아래처럼 많이 비교하게 됩니다. 하지만, 잠재적으로 문제상황을 내재를 하고 있죵..

public void compareType(Stirng type)
{
    if(type.equals(“AAA”))
        …
    else if(type.equals(“BBB”))
        …
    else if(type.equals(“CCC”))
        …
}

위의 코드를 아래처럼 바꾸게 되면, 잠재적인 NullPointerException 상황을 피할수 있네요.

public void compareType(Stirng type)
{
    if(“AAA”.equals(type))
        …
    else if(“BBB”.equals(type))
        …
    else if(“CCC”.equals(type))
        …
}

위 내용은 http://entireboy.egloos.com/2411775 에서 참고를 하였습니다.

BufferedWriter vs BufferedOutputStream 성능차이..

로그 데이터를 파일에 저장하기 위해서 BufferedWriter 클래스를 사용하다가, 갑자기 BufferedOutputStream으로 처리하는 것과의 성능상 차이에 대해서 확인하고 싶어서, 동일한 데이타를 파일에 저장해 봤다. 두 클래스의 성능 차이는 별로 없어 보이지만 그래도 확인 해 보자. 아래의 BufferWriterTest, BufferOutputStream 클래스의 buffersize는 1024로 동일하다.

– BufferWriterTest.java

import java.util.*;
import java.text.*;
import java.io.*;

public class BufferWriterTest {
	//
	static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

	static String txt = "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하" + "가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하마바사아자차타파하";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Date start = new Date();
		System.out.println("s – " + df.format(start));

		BufferedWriter bufferWriter;

		try {
			bufferWriter = new BufferedWriter(new FileWriter("c:\\BufferedWriter.txt", true), 1024);
			for (int i = 0; i < 5000000; i++) {
				bufferWriter.write(BufferWriterTest.txt);
				bufferWriter.newLine();
			}

			bufferWriter.flush();
			bufferWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		Date end = new Date();
		System.out.println("e – " + df.format(end));
	}
}

결과(3.15G 파일 쓰기)

s – 2009-06-19 15:55:00:968
e – 2009-06-19 15:55:48:280

– BufferOutputStreamTest.java

import java.io.IOException;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class BufferOutputStreamTest {
	//
	static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
	static String txt = "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ 	"가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라"
			+	"가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ 	"가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+	"가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" 
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하"
			+ "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" 
			+ 	"가나다라마바사아자차타파하마바사아자차타파하";

	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Date start = new Date();
		System.out.println("s – " + df.format(start));

		BufferedOutputStream bufferedOutput;
		try {
			bufferedOutput = new BufferedOutputStream(new FileOutputStream("c:\\BufferedStream.txt", true), 1024);

			for (int i = 0; i < 5000000; i++) {
				bufferedOutput.write(txt.getBytes());
				bufferedOutput.write("\n".getBytes());
			}
			bufferedOutput.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		Date end = new Date();
		System.out.println("e – " + df.format(end));
	}
}

결과(3.15G 파일 쓰기, )

s – 2009-06-19 15:56:41:889
e – 2009-06-19 15:58:19:825

위 결과를 보면, 비슷한 사이즈의 파일을 추가할 경우에 꽤 성능차이가 난다. 느낌에는 비슷한 성능을 낼 것으로 생각이 드는데, 스트링 처리는 Reader/Writer 시리즈가 더 적합하다는 것인가? 혹시 아래의 구조 때문에 그럴까요? 아시는 분은 조언을..

BufferedWriter BufferedOutputStream
java.lang.Object
– java.io.Writer
– java.io.BufferedWriter
java.lang.Object
– java.io.OutputStream
– java.io.FilterOutputStream
– java.io.BufferedOutputStream