프로그램/java

java Collection Tester (java Collections static utility 사용 예제)

mulderu 2011. 9. 15. 21:02

Java API 사용법을 잘 알아두는건, 좋은 코딩을 하기 위한 아주 중요한 조건이다.
Java API 중 많이 알려 지는 않는 Class 가 Collections ( java.util.Collections ) 


아래는 java api doc 의 설명 입니다. 

 

아래는 제가 Collections class 의 정적멤버 몇가지를 테스트 하기 위한 소스 입니다.
대충 주석을 보면 그 용도가 금방 나올겁니다..
아래쪽에 Thread Safety 관련 부분은 List나 Map같은 데이터를 Thread에서 공유할때 얼마나 위험한지를 테스트 해보기
위해 만들었습니다... 


package com.util.tester;

import java.util.*;

public class CollectionTester {
    
	// 간단히 정해진 크기의 문자열 리스트를 리턴한다.
	public static List getTestList() {
		List testList = Arrays.asList("mulder","scully","alien","mb", "멀더" , "스컬리");
		return testList;
	}
	
	
	
	// 리스트의 크기만큼 같은 문자열(오브젝트)로 채운다.
	public static void testFill() {
		List list = getTestList();
		Collections.fill(list, "zzz");
		printTestList(list);
	}
	
	// 리스트의 멤버를 역순으로 다시 채운다.
	public static void testReverse() {
		List list = getTestList();
		Collections.reverse(list);
		printTestList(list);
	}
	
	// 리스트내에서 원하는 object를 치환시킨다.
	public static void testReplaceAll() {
		List list = getTestList();
		Collections.replaceAll(list, "mulder", "youngsung");
		printTestList(list);
	}
	
	// 리스트내에서 원하는 서브리스트의 첫번째 만나는 인덱스를 리턴 해 준다.
	public static void testIndexOfSubList() {
		List list = getTestList();
		List subs = Arrays.asList("scully","alien");
		
		int n = Collections.indexOfSubList(list, subs);
		System.out.println("int n = Collections.indexOfSubList(list, subs); =>" + n);
	}
	
	// 리스트의 원소들을 원하는 만큼 로데이트(우측방향으로 모두 이동) 시켜준다. :)
	public static void testRotate() {
		List list = getTestList();
		Collections.rotate(list, 2);
		printTestList(list);
	}
	
	// 소팅..
	public static void testSort() {
		List list = getTestList();
		Collections.sort(list);
		printTestList(list);
	}
	
	// 일반 리스트의 Thread param add/remove tester
	public static void testNormalListAddRemove() {
		List list = new ArrayList(); // 
		list.add("1");list.add("2");list.add("3");list.add("4");
		
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(list)).start();
		}
		System.out.println("");
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(list)).start();
		}

		System.out.println("");
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(list)).start();
		}
		System.out.println("");
		
	}
	
	// synchronizedList 이거 사용한다고  Thread 순서꼬임을 해결하는게 절대 아니다...
	// add/remove는 thread safe하지만 size(), get()에서는 안전하지 않다.
	//
	// thread safe하게 코딩을 하려면 해당 지점이나 method 를 synchronized 로 묶어 주여야 만 한다.
	public static void testSyncronizedListAddRemove() {
		List list = new ArrayList(); // 
		list.add("1");list.add("2");list.add("3");list.add("4");
		
		List syncList = Collections.synchronizedList( list );
		
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(syncList)).start();
		}
		System.out.println("");
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(syncList)).start();
		}

		System.out.println("");
		for(int i=0; i<500; i++) {
			new Thread(new MyWorker(syncList)).start();
		}
		
	}
	
	public static void testUnmodifiableList() {
		List list = Collections.unmodifiableList( getTestList() );
		list.add("error .... ocurr !!!"); // 이거 하면서 Exception : java.lang.UnsupportedOperationException
		printTestList(list);
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		testShuffle();
		testShuffle();
		
		testFill();
		testReverse();
		testReplaceAll();
		testIndexOfSubList();
		
		testRotate();
		testSort();
		
		//testNormalListAddRemove(); //
		testSyncronizedListAddRemove(); // 절차에 있어서는 thread safe하지 않다... exception
		
		// testUnmodifiableList(); // 호출하면 바로 에러 나는 함수...임.

	}

	
	// 간단히 문자열리스트 프린트아웃하기.
		public static void printTestList(List list) {
			System.out.println("===================");
			for(String s : list) {
				System.out.println("----" + s);
			}
			System.out.println("~~~~~~~~~~~~~~~~~~");
		}
		
		// 리스트내의 원소들을 섞는다..랜덤함수를 이용하여 재정렬하는것과 같다.
		public static void testShuffle() {
			List list = getTestList();
			Collections.shuffle(list);
			printTestList(list);
		}
}

//----------------------------------------------------------------------------------------------------------

package com.util.tester;

import java.util.List;

public class MyWorker implements Runnable {
	static int count  = 0;
	List list; // 공유 리스트
	public MyWorker(List list) {
	    this.list = list;	
	}

	@Override
	public void run() {
		count++;
		
		list.add("5");
		
		if(list.size()>5) System.out.print("["+list.size()+"/"+count + "]"); 
		
		// thread 간 간섭시간을 벌기 위해 0.01초간 쉰다.
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		

		String s;
		//String s = list.remove(list.size()-1);

                //아래 부분에서 remove 의 파라미터 index 가 thread safe 하지 않아서 문제가 된다.
		s = list.remove(list.size()-1);  // 여기서 리턴 받는다...
		
		// System.out.print(s + ",");
		
		count--;
	}

}