1.State


State는 Thread의 작업을 감시하는 역할을 한다.


스레드의 상태가 어떤지 지속적으로 알려주는 기능이다.


활용도는 낮은편..



package chap10.exam06.state;

public class WorkThread extends Thread {

	@Override
	public void run() {

		for(long i=0; i<1000;i++) {
			System.out.println(i);
		}

		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		for(long i=0; i<1000;i++) {
			System.out.println(i);
		}

	}
	
}
package chap10.exam06.state;

public class Main {
	
	private static Thread.State state;

	public static void main(String[] args) throws InterruptedException {
		/*워크 스레드 : 생성 -> 실행 -> 일시정지 -> 실행 -> 종료*/
		/*메인스레드 : 워크스레드를 감시*/
		WorkThread work = new WorkThread();

		//메인 스레드는 지속적으로 워크 스레드를 감시
		while(true) {
			state = work.getState();
			System.out.println("THREAD STATE : "+state);
			//객체 생성시 워크 스레드 실행
			if(state == Thread.State.NEW) {
				work.start();
			}			
			/*Runnable 이 순식간에 진행 되므로 잘 잡히지 않는다.
			Sleep 을 제거 하면 볼수는 있다.
			*/			
			Thread.sleep(500); //0.5초 휴식
			
			if(state == Thread.State.TERMINATED) {
				break;
			}
			
		}

	}

}





2.Control(sleep, yield, join, wait, notify, stop, interrupt)


2-1 sleep, yield


sleep은 Thread를 대기 시키는 메소드로 안에 인자를 받는데 mil second로 1000값을 주면 1초동안 Thread를 대기 시킨다.


yield는 작업을 셀프 인터럽트 시키는 메소드로 작업을 다음 순서 스레드에게 양보한다고 이해하면 된다.



package chap10.exam07.yield;

public class ThreadA extends Thread {
	
	boolean stop = false;
	boolean yield = false;

	@Override
	public void run() {
		
		while(!stop) {
			System.out.println("Thread A 동작");
			if(yield) {
				System.out.println("Thread B 에게 양보");
				Thread.yield();
			}			
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Thread A 중지");

	}
	
	

}
package chap10.exam07.yield;

public class ThreadB extends Thread {
	
	boolean stop = false;
	boolean yield = false;

	@Override
	public void run() {
		
		while(!stop) {
			System.out.println("Thread B 동작");
			if(yield) {
				System.out.println("Thread A 에게 양보");
				Thread.yield();
			}			
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Thread B 중지");

	}

}
package chap10.exam07.yield;

public class MainThread {

	public static void main(String[] args) throws InterruptedException {
		/*
			yield 는 자신이 쉬겠다는 의미가 아님
			다른 스레드에게 할 수 있는 기회를 양보 하는 것
			실행 순서 정도에 변화를 줄 수 있다.
		*/

		//A,B 스레드 생성 후 실행
		ThreadA thA = new ThreadA();
		ThreadB thB = new ThreadB();
		thA.start();
		thB.start();		
		
		//A 에게 양보 하라고 함(B 에게 우선권 양보)
		thA.yield = true;
		Thread.sleep(1000);
		//B 에게 양보 하라고 함(A 에게 우선권 양보)
		thB.yield = true;
		Thread.sleep(1000);		
		
		//A,B 정지
		thA.stop = true;
		thB.stop = true;	
		
	}

}



2-2. join


스레드가 병렬로 처리 될 경우 작업 자체가 분리되는 부분이 있는데 join을 사용하면 작업이 공통 처리된다.


다음 예제는 메인 스레드와 oper 스레드가 join을 사용했을 때와


주석처리하여 사용하지 않았을 때의 결과를 비교하는 예제이다.


한번 직접 oper.join(); 을 주석처리하여 테스트 해보자.



package chap10.exam08.join;

public class OperThread extends Thread{

	private int sum = 0;
	
	@Override
	public void run() {		
		for(int i=1; i<=100; i++) {
			sum += i;
		}
	}

	public int getSum() {
		return sum;
	}

}
package chap10.exam08.join;

public class MainThread {

	public static void main(String[] args) throws InterruptedException {
		//1~100 까지의 합
		OperThread oper = new OperThread();
		oper.start();//oper : 실제 계산 수행
		
		oper.join();//oper 와 같이 가라, 이 줄을 주석처리 하여 테스트
		//oper 의 수행 내용이 끝나고 나면 아래가 실행 된다.
		//main : 계산 내용을 출력
		System.out.println("1~100 의 합 : "+oper.getSum());
	}

}




2-3. wait, notify


wait은 스레드를 대기상태로 만들고


notify는 스레드 중 하나를 실행대기 상태로 만들고


notifyall은 스레드 전체를 실행대기 상태로 만든다.


대기상태는 작업을 일시정지 하는것이고 실행대기는 작업 대기열에 넣어 연산을 준비하는 것이다.



package chap10.exam10.test;

public class CommonData {
	
	private String data = null;
	//wait(), notify() 등을 호출하기 위해서는 synchronized 필요
	public synchronized void getData() {
		try {			
			if(data != null) {//1. 데이터가 있으면 가져온다.
				System.out.println("가져온 데이터 : "+this.data);
				this.data = null;//가져왔으면 비워주고
			}			
			notify();	//2. 깨우고
			wait();		//3. 난 쉰다.
		} catch (InterruptedException e) {
			e.printStackTrace();
		}	
	}

	public synchronized void setData(String data) {		
		try {
			//1. 데이터가 없으면 만든다.
			if(this.data == null) {
				System.out.println("넣을 데이터 : "+data);
				this.data = data;
			}			
			notify();	//2. 넣고 나면 깨우고
			wait();		//3. 난 쉰다.
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
	}	

}
package chap10.exam10.test;

public class Consumer extends Thread{
	
	private CommonData data;

	public Consumer(CommonData data) {
		this.data = data;
	}

	@Override
	public void run() {
		for(int i=1; i<=5;i++) {
			data.getData();
		}
	}	

}
package chap10.exam10.test;

public class Producer extends Thread{
	
	private CommonData data;

	public Producer(CommonData data) {
		this.data = data;
	}

	@Override
	public void run() {
		for(int i=1; i<=5;i++) {
			data.setData("DATA_"+i);
		}
	}	

}
package chap10.exam10.test;

public class Main {

	public static void main(String[] args) throws InterruptedException {
		
		CommonData data = new CommonData();
		
		Producer pro = new Producer(data);
		Consumer con = new Consumer(data);
		pro.start();
		Thread.sleep(10);
		con.start();

	}

}






2-4. stop, interrupt


stop과 interrupt는 Thread 작성 시 run에서 작업중인 내용일 종료시켜버린다.


Thread는 보통 while(true)를 통해서 무한루프를 돌려 감시체계를 만든다던가 특정 작업을 받기위해 대기하고 있다던가


그러한 경우로 자주 쓰이기 때문에 강제 종료해주는 기능이 필요할 때가 있다.


이때 stop() 을 사용 할 수 있으나 현재는 사용중지를 권고 하고 있다.



package chap10.exam11.stop;

public class Inter extends Thread {

	@Override
	public void run() {
		/*
		try {
			while(true) {
				System.out.println("Inter 실행 중");
				Thread.sleep(1);
			}
		} catch (InterruptedException e) {
			System.out.println("자원 정리");
			System.out.println("종료");
		}
		*/
		while(true) {
			System.out.println("Inter 실행 중");
			if(Thread.interrupted()) {
				break;
			}
		}
		System.out.println("자원 정리");
		System.out.println("종료");
		
	}
	
	

}
package chap10.exam11.stop;

public class StopFlag extends Thread {	
	
	private boolean stop = false;
	
	public void setStop(boolean stop) {
		this.stop = stop;
	}
	
	@Override
	public void run() {		
		while(!stop) {
			System.out.println("StopFlag 실행중");
		}
		System.out.println("자원 정리");
		System.out.println("종료");
	}
}
package chap10.exam11.stop;

public class MainThread {

	public static void main(String[] args) throws InterruptedException {
		/*Stop Flag 이용*/
		StopFlag flag = new StopFlag();
		flag.start();
		Thread.sleep(1000);
		flag.setStop(true);
		
		/*강제 인터럽트 이용*/
		Inter inter = new Inter();
		inter.start();
		Thread.sleep(1000);
		inter.interrupt();//강제로 인터럽트 예외를 발생
			

	}

}


'개념 및 코딩 > 08.Thread 스레드' 카테고리의 다른 글

[JAVA]08-07.Thread Pool, Pool Block  (0) 2018.09.06
[JAVA]08-05.Demon Thread  (0) 2018.09.06
[JAVA]08-03.Priority, Synchronized  (0) 2018.09.06
[JAVA]08-02.Runnable, Thread  (0) 2018.09.04
[JAVA]08-01.Thread  (0) 2018.09.04

1.Priority


Thread에 우선순위를 부여하여 실행하는 것이다.


너무 짧은 작업이라면 우선순위 부여에 의미가 없지만 작업이 커질수록 차이가 느껴질 것이다.



package chap10.exam04.priority;

public class WorkThread extends Thread {

	public WorkThread() {
		// TODO Auto-generated constructor stub
	}

	public WorkThread(String name) {
		setName(name);
	}

	@Override
	public void run() {
		System.out.println(getName() + "의 작업 시작");
		for(int i = 0; i < 100000; i++) {
			// 이 시간동안 작업이 있다고 가정
		}
		System.out.println(getName() + "의 작업 끝");
	}

}
package chap10.exam04.priority;

public class Main {

	public static void main(String[] args) {
		// 우선 순위는 1~10까지 줄 수 있다.
		// 우선 순위가 같거나 없으면 무조건 빠른놈이 먼저다.
		// 우선 순위는 상수로도 가능하다.
		
		for(int i = 1 ; i <= 5; i++) {
			Thread th = new WorkThread(i + "번째 스레드");
			th.setPriority(i);
//			th.setPriority(Threa[d.MAX_PRIORITY);
//			th.setPriority(Thread.MIN_PRIORITY);
//			th.setPriority(Thread.NORM_PRIORITY);
			th.start();
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 우선순위만으로는 완벽한 스레드 제어가 어렵다
		}
	}

}



2.Synchronized


Thread는 메모리를 공유하는 특성이 있기 때문에 데이터의 간섭이 일어날 수 있다.


두 개의 thread가 돌아갈 때에 같은 데이터를 수정한다면 작업의 순서도 예측하기 어렵고 값이 어떻게 바뀔지도 모르게 된다.


Synchronized는 코드를 { }괄호로 감싸서 thread가 그 부분을 읽을 때 다른 thread에서 읽지 못하게 잠궈버린다.


먼저 들어온 thread가 작업을 마치고 다음 thread가 작업을 실행하게 된다.



package chap10.exam05.sync;

public class Computer {
	private int score;

	// 동기화 이전
	//	public void setScore(int score) {
	//		this.score = score;
	//		try {
	//			Thread.sleep(2000); // 2초 슬립 (이 사이 다른 사용자가 정보 변경 가능)
	//		} catch (InterruptedException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//		} 
	//		System.out.println(Thread.currentThread().getName() + " : " + this.score);
	//	}

	// 동기화 메소드 방식 : 메소드 접근을 제한
	//	public synchronized void setScore(int score) {
	//		this.score = score;
	//		try {
	//			Thread.sleep(2000); // 2초 슬립 (이 사이 다른 사용자가 정보 변경 가능)
	//		} catch (InterruptedException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//		} 
	//		System.out.println(Thread.currentThread().getName() + " : " + this.score);
	//	}

	// 동기화 블록 방식 : 메소드 까지는 허용, 특정 구역에서 제한

	public void setScore(int score) {
		// 스레드 들이 들어와서 작동할 수 잇음
		synchronized (this) { // this는 현재 Computer 객체
			this.score = score;
			try {
				Thread.sleep(2000); // 2초 슬립 (이 사이 다른 사용자가 정보 변경 가능)
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			System.out.println(Thread.currentThread().getName() + " : " + this.score);
		}
	}
}
package chap10.exam05.sync;

public class User1 extends Thread{
	private Computer com;
	public User1(Computer com) {
		setName("user 1");
		this.com = com;
	}
	@Override
	public void run() {
		com.setScore(500); // user 1은 점수를 500으로 만든다.
	}
	

}
package chap10.exam05.sync;

public class User2 extends Thread {
	private Computer com;
	
	public User2(Computer com) {
		setName("user 2");
		this.com = com;
	}

	@Override
	public void run() {
		com.setScore(100); // user2는 점수를 100으로 만든다.
	}

}
package chap10.exam05.sync;

public class PcRoom {

	public static void main(String[] args) {
		// 공용 컴퓨터 만들기
		Computer com = new Computer();
		//user1에게 컴 사용 하게 해줌
		User1 user1 = new User1(com);
		user1.start();
		//user2에게 컴 사용 하게 해줌
		User2 user2 = new User2(com);
		user2.start();
	}

}


'개념 및 코딩 > 08.Thread 스레드' 카테고리의 다른 글

[JAVA]08-07.Thread Pool, Pool Block  (0) 2018.09.06
[JAVA]08-05.Demon Thread  (0) 2018.09.06
[JAVA]08-04.Thread State, Control  (0) 2018.09.06
[JAVA]08-02.Runnable, Thread  (0) 2018.09.04
[JAVA]08-01.Thread  (0) 2018.09.04

1.Runnable, Thread


쓰레드는 전에 설명했듯이 작업을 병렬적으로 수행할 때에 사용하는데


실제로는 두개가 나란히 작동되는게 아니고 라운드로빈이라는 스케줄링 기법을 사용한다.


라운드로빈을 사용하기에 매번 똑같은 결과를 얻을 수 없고 작업 순서가 매번 다르게 실행된다.


CPU의 계산을 최대한 효율적이고 모든 프로그램에 공평하게 할당하기 위해 만들어낸 여러가지 기법들 중 하나이다.


Java에서는 Runnable인터페이스나 Thread 클래스를 상속 받아 멀티 스레드를 구현할 수 있다.


Runnable의 경우는 run메소드 작업을 정의 한 후 Thread 생성 시 안에 집에 넣는다.


Runnable로 따로 정의하지 않고 Thread의 오버라이드 된 run에 바로 정의를 하여도 문제가 없어 보통은 Thread만 단독으로 자주 쓴다.


익명객체를 사용하여 객체 선언과 동시 메소드를 1회용으로 만들수 있다.


다음 예제를 확인해보자.






package chap10.exam01.runnable;

public class Job implements Runnable {

	@Override
	public void run() {
		for(int i = 0; i < 5; i++) {
			System.out.println("워크 스레드 실행");
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}
package chap10.exam01.runnable;

public class MainThread {

	// Main Thread를 main에서 발생 시킨다.
	// 굉장히 중요
	public static void main(String[] args) {
		
		// 함께 일해줄 WorkThread 생성(Runnable)
		// 1. work thread가 해야할 일 생성
		Runnable job = new Job();
		// 2. 일 해줄 스레드 생성
		Thread thread = new Thread(job);
		// 3. 일을 시킨다. (무조건 start로 시작함)
		thread.start();
		// 동시 실행 테스트
		for(int i = 0; i < 5; i++) {
			System.out.println("메인 스레드 실행");
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}



익명객체를 이용한 스레드


package chap10.exam01.runnable;

public class AnonyMain {

	public static void main(String[] args) {
		// 스레드 생성(할 일) 과 같이 생성
		// 익명객체, 따로 java파일을 만들 필요가 없음
		Thread thread = new Thread() {			
			@Override
			public void run() {
				for(int i = 0; i < 5; i++) {
					System.out.println("워크 스레드 실행");
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		};
		// 스레드 실행
		thread.start();
		
		// 메인에서 실행할 작업
		for(int i = 0; i < 5; i++) {
			System.out.println("메인 스레드 실행");
			try {
				Thread.sleep(400);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}


'개념 및 코딩 > 08.Thread 스레드' 카테고리의 다른 글

[JAVA]08-07.Thread Pool, Pool Block  (0) 2018.09.06
[JAVA]08-05.Demon Thread  (0) 2018.09.06
[JAVA]08-04.Thread State, Control  (0) 2018.09.06
[JAVA]08-03.Priority, Synchronized  (0) 2018.09.06
[JAVA]08-01.Thread  (0) 2018.09.04

1.Thread


스레드는 작업을 수행하는 단위로 단순하게 cpu의 코어가 2개, 듀얼 코어라면 2개의 작업(스레드)을 동시에 할 수 있다.


지금까지의 작업은 싱글 스레드, 하나의 작업을 돌린것이다.


이 스레드를 이용하면 여러가지의 작업들 동시에, 병렬적으로 처리 할 수 있다.


public static void main(String[] args)가 있는 스레드를 메인 스레드라고 하고


스레드를 추가하여 병렬작업을 하는것을 멀티 스레딩이라고 한다.


멀티 스레딩의 장단점으로는 아래와 같다.


 - 장점


CPU 이용률 향상

효율적인 자원 활용

수행 기능별로 분리하여 코드가 간결해짐

어플리케이션의 응답성 향상


 - 단점


같은 프로세스의 자원을 공유하므로 동기화가 필요

동기화 처리에 관한 이슈 처리 필요(교착상태, 기아상태 등)

CPU환경이나 OS의 스케줄러를 고려해야 함

'개념 및 코딩 > 08.Thread 스레드' 카테고리의 다른 글

[JAVA]08-07.Thread Pool, Pool Block  (0) 2018.09.06
[JAVA]08-05.Demon Thread  (0) 2018.09.06
[JAVA]08-04.Thread State, Control  (0) 2018.09.06
[JAVA]08-03.Priority, Synchronized  (0) 2018.09.06
[JAVA]08-02.Runnable, Thread  (0) 2018.09.04

1.스택(Stack)


스택과 큐는 자료구조를 공부한다면 바로 접할 수 있는 그 스택과 큐다.


스택은 LIFO(Last in First Out)으로 마지막으로 들어온 자료가 처음으로 나온다. 의미 그대로의 자료 구조를 가지고 있다.


수건을 예로 든다면 잘 개어진 수건을 사용한다고 할 때에 수건을 개어서 쌓아서 보관을 한다.


1. 쌓아서 차곡차곡 위에 올려서 보관하고


2. 꺼내 쓸 때에는 맨 위부터 하나씩 빼게 된다.


스택의 자료구조도 이와 같은 느낌이다.


Java에서도 사용 할 수 있게 구현이 되어있다 다음 예를 통해 메소드 활용과 함께 확인해보자



package chap09.exam05.stack;

public class Towel {
	
	private String color;

	public Towel(String color) {
		this.color = color;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}	

}
package chap09.exam05.stack;

import java.util.Stack;

public class TowelBox {

	public static void main(String[] args) {

		// 수건통
		Stack<Towel> box = new Stack<Towel>();
		
		// 넣기(push)
		box.push(new Towel("red"));
		box.push(new Towel("orange"));
		box.push(new Towel("yellow"));
		box.push(new Towel("green"));
		box.push(new Towel("blue"));
		box.push(new Towel("blush violet"));
		box.push(new Towel("purple"));
		System.out.println(box.size());
		
		// 수건 빼기
		Towel towel = box.pop();
		System.out.println(towel.getColor());
		System.out.println(box.size());
		
		// 타올을 뺀 다음 색상 확인(메소드 체이닝)
		System.out.println(box.pop().getColor());
		System.out.println(box.size());
		
		// 남아있는 수건을 하나씩 뽑아서 모두 색상을 확인
		int number = box.size();
		for(int i = 0; i < number; i++) {
			System.out.println(box.pop().getColor());
			System.out.println(box.size());
		}
		// for문이나 while문 셋 중 두개만 주석(ctrl + /)처리해서
		// 테스트 해보면 같은 결과를 얻을 수 있음
		while(box.size() > 0) {
			// pop은 값을 확인하고 버림
			System.out.println(box.pop().getColor());
			// peek은 값을 확인만 함
//			System.out.println(box.peek().getColor());
			System.out.println(box.size());
		}
		// 향상된 for에서 내부적으로 pop을 사용하지 않고 있음
		for(Towel item:box) {
			System.out.println(item.getColor());
			System.out.println(box.size());
		}
	}

}



2.큐(Queue)


큐는 스택과 마찬가지로 대표적인 자료구조로 FIFO구조로 이루어진다.


First In First Out이고 처음 들어온 자료가 처음부터 나가는것이다.


마찬가지로 예를 든다면


1. 가게에 물건을 사러 1~5번 손님이 번호에 맞춰 순서대로 계산대에 서게 된다면


2. 1번 손님이 먼저 왔으니 먼저 계산하는 구조


이와 같이 큐는 들어온 순서대로 나가는 구조이다.



package chap09.exam06.queue;

public class Job {

	private String command;
	private String to;
	
	public Job(String command, String to) {
		this.command = command;
		this.to = to;
	}
	
	//command와 to의 수정을 허용하지 않으므로 getter만 만듬

	public String getCommand() {
		return command;
	}

	public String getTo() {
		return to;
	}
	

}
package chap09.exam06.queue;

import java.util.LinkedList;
import java.util.Queue;

public class JobList {

	public static void main(String[] args) {
		// Queue 생성 - 내부구조는 링크드 리스트
		Queue<Job> list = new LinkedList<Job>();
		// 값을 넣을 때 offer
		list.offer(new Job("Send SMS", "A"));
		list.offer(new Job("Send Mail", "B"));
		list.offer(new Job("Send SMS", "C"));
		list.offer(new Job("Send Kakao", "D"));
		list.offer(new Job("Send Call", "E"));
		
		// 등록된 해야할 일(누구에게 무얼 하는지)을 모두 확인 하기
		// 값을 뺄 때 poll
		// peek 확인만 할 때
		// size를 통해 크기 확인
		// isEmpty
//		System.out.println(list.isEmpty());
//		System.out.println(list.size());
//		System.out.println(list.poll().getTo() + "의 다음 사람에게 할 일 : " + list.poll().getCommand());
//		System.out.println(list.poll().getTo() + "의 다음 사람에게 할 일 : " + list.poll().getCommand());
//		System.out.println(list.peek().getTo() + "에게 할 일 : " + list.poll().getCommand());
//		System.out.println(list.size());
//		System.out.println(list.isEmpty());
		
		while(list.size() > 0) {
			System.out.println("남은 작업 개수 : " + list.size());
			Job j = list.poll();
			System.out.println(j.getCommand() + " to " + j.getTo());
		}
	}

}


주석문은 직접 지웠다가 다시 붙였다가 하며 테스트를 해보자(Ctrl+/)

'개념 및 코딩 > 07.Collection Framework' 카테고리의 다른 글

[JAVA]07-04.HashMap, HashTable  (0) 2018.09.04
[JAVA]07-03.Hashset  (0) 2018.09.04
[JAVA]07-02.ArrayList, LinkedList  (0) 2018.09.04
[JAVA]07-01.Collection, Map  (0) 2018.09.04

1.HashMap, HashTable


해쉬 맵과 해쉬 테이블은 Key와 Value를 저장하는데 Key는 데이터를 구분할 이름이라 이해하고


Value는 내용인 값이 저장될 자리이다.


해쉬의 값은 key값을 알아야만 Value값을 추출 할 수 있고 key값을 알 경우에는 상관 없지만


모를 경우에는 Iterator을 이용해 key값을 추출 할 수 있다.


만약 key value값을 둘 다 빼내고 싶다면 Entry와 Iterator을 같이 이용하면 된다. 아래 예제를 확인해보자


맵과 테이블의 차이점은 동기화의 유무이다. 다중 스레드(동시 작업)을 이용 할 경우 맵의 경우는 동기화를 하지 않고


테이블의 경우는 동기화를 해준다.


테이블은 동기화를 하기 때문에 맵에 비해서 자원의 소모가 조금 더 있는 편이다.



package chap09.exam04.map;

import java.util.Map.Entry;
import java.util.HashMap; // <- impor문 정리하는 방법
import java.util.Iterator;
import java.util.Set;
									// Ctrl + shift + O

public class HashMapEx {

	public static void main(String[] args) {
		// HashMap = Key - Value  << 중요, 많이 쓰임
		HashMap<String, Integer> map = new HashMap<String, Integer>();
		
		map.put("kim",  23); // value의 Type을 반환하게 되어있다.
		map.put("lee",  26);
		map.put("park",  26);
		map.put("kim",  37); // 키가 중복인 경우 덮어쓴다.
		System.out.println(map.size());
		// 맵에서 값 꺼내기(키를 이용하여 빼온다)
		System.out.println(map.get("lee"));
		
		// map의 모든 값을 출력 1 : 키 값만 이용하여 추출
		// key 만 가져온다.
		Set<String> keySet = map.keySet();
		// key를 조각 낸다.
		Iterator<String>iter = keySet.iterator();
		//key로 value를 하나씩 가져온다.
		while(iter.hasNext()) { // 값이 존재 하는가?
			String key = iter.next(); // 있으면 뽑아온다.
			System.out.println(map.get(key));
		}
		System.out.println();
		for(String key : keySet) {
			System.out.println(map.get(key));
		}
		
		// map의 모든 값을 출력 2 : 키-값 단위로 가져온 후 추출
		// map에서 entry를 뽑아옴 : entry (key-value 한 쌍으로 잘라줌)
		Set<Entry<String, Integer>> entry = map.entrySet();
		// 가져올 수 있도록 잘라줌
		Iterator<Entry<String, Integer>> iterlator = entry.iterator();
		// 하나씩 꺼내옴(키-값 한 쌍)
		while(iterlator.hasNext()) {
			Entry<String, Integer> item = iterlator.next();
			// entry로 부터 키와 값을 뽑아냄
//			String key = item.getKey();
//			int value = item.getValue();
			System.out.println(item.getKey() + " : " +  item.getValue());
		}
	}

}
package chap09.exam04.map;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class HashTableEx {

	public static void main(String[] args) {
		// 사용법은 HashMap과 동일
		Map<String, Integer> map = new Hashtable<String, Integer>();
		map.put("a", 70);
		map.put("b", 80);
		map.put("c", 60);
		map.put("d", 90);
		map.put("e", 75);
		map.put("f", 45);
		map.put("g", 30);
		map.put("h", 50);
		map.put("i", 55);
		map.put("j", 99);
		
		// 찾는 키가 있으면 키의 값을 보여주고, 없으면 없다고 알림
		// 찾는 이름 : d
		if(map.containsKey("d")) {
			System.out.println("d의 점수 : " + map.get("d"));
		} else {
			System.out.println("찾으시는 값은 없어염");
		}
		
		// 99점 학생이 존재 하는지?
		if(map.containsValue(99)) {
			System.out.println("99점이 있었네...");
		} else {
			System.out.println("찾으시는 분은 안계세yo");
		}
		
		// 99점 학생은 누구인가?(값으로 키를 찾는 방법)
		
		// 키셋 방법
		Set<String> keySet = map.keySet();
		// key를 조각 낸다.
		Iterator<String>iter = keySet.iterator();
		//key로 value를 하나씩 가져온다.
		while(iter.hasNext()) { // 값이 존재 하는가?
			String key = iter.next(); // 있으면 뽑아온다.
			int value = map.get(key);
			if(value == 99) {
				System.out.println("99점인 사람 : " + key + ", " + value);
			}
		}
		
		// 엔트리 방법
		// 1. map의 entry(키-값)을 set으로 반환
		Set<Entry<String, Integer>> entries = map.entrySet();
		// 2. 잘라낼 수 있도록 Iterator 화
		Iterator<Entry<String, Integer>> iter2 = entries.iterator();
		// 3. 하나씩 뽑아내서 값을 비교
		while(iter2.hasNext()) {
			Entry<String, Integer> item = iter2.next();
			if(item.getValue() == 99) {
				System.out.println("99점 학생 : " + item.getKey());
			}
		}
		
		// 번외 향상된 for문 가능?
		for(Entry<String, Integer> item : entries) {
			System.out.println(item.getKey() + " : " + item.getValue());
		}
	}

}


'개념 및 코딩 > 07.Collection Framework' 카테고리의 다른 글

[JAVA]07-05.Stack, Queue  (0) 2018.09.04
[JAVA]07-03.Hashset  (0) 2018.09.04
[JAVA]07-02.ArrayList, LinkedList  (0) 2018.09.04
[JAVA]07-01.Collection, Map  (0) 2018.09.04

1.HashSet


HashSet은 하나씩 저장되고 중복을 혀용하지 않는 컬렉션이다.


HashSet부터는 자료를 입력할 때에는 상관없으나 꺼내올 때에는 따로 Iterator라는 인터페이스를 사용해야 한다.


다음 예제를 작성하여 눈에 익혀보자


예제의 클래스 파일을 HashSet이라 명명하고 사용 할 경우 사용할 HashSet과 이름이 겹치게 된다.


그러므로 구분을 위해서 java.util.HashSet처럼 표시되지만 이러한 클래스 파일 명명은 쓰지 않는것이 좋다.



package chap09.exam03.hashset;

import java.util.Iterator;
import java.util.Set;

public class HashSet {

	public static void main(String[] args) {
		
		// 사용하는 클래스와 현재의 클래스 명이 같으면 객체화 시
		// 경로까지 표시된다.
		Set<String> set = new java.util.HashSet<String>();
		Set<Member> member = new java.util.HashSet<Member>();
		
		set.add("JAVA");
		set.add("ORACLE");
		set.add("MVC");
		set.add("JSP");
		set.add("JAVA"); // 중복이라서 입력되지 않음
		System.out.println(set.size());
		member.add(new Member());
		member.add(new Member()); // 중복이지만 객체는 복사본으로 중복으로 보지 않음
		System.out.println(member.size());
		
		
		
		// 하나씩 뽑아 오기 1번
		// set -> iterator : 조각내기 -> next() : 뽑아오기
		Iterator<String> iter = set.iterator();
		while(iter.hasNext()) {
			String item = iter.next();
			System.out.println(item);
		}
		
		// 삭제
		set.remove("ORACLE");
		
		// 하나씩 뽑아 오기 2번
		for(String item : set) {
			System.out.println("향상된 for : " + item);
		}

		// 비우기
		set.clear();
		// 비어있는지 확인
		System.out.println("비어있을까? : " + set.isEmpty());
	}

}

class Member{
	
}



'개념 및 코딩 > 07.Collection Framework' 카테고리의 다른 글

[JAVA]07-05.Stack, Queue  (0) 2018.09.04
[JAVA]07-04.HashMap, HashTable  (0) 2018.09.04
[JAVA]07-02.ArrayList, LinkedList  (0) 2018.09.04
[JAVA]07-01.Collection, Map  (0) 2018.09.04

1.ArrayList


어레이 리스트는 배열과 똑같이 0번방부터 시작해서 자료가 들어오는대로 1, 2, 3, ~ 늘어나는 구조이다.


배열을 쓰다가 ArrayList를 배운다면 배열을 잘 쓰지 않게 될 것이다.


배열과 달리 크기를 따로 지정할 필요 없고 add를 통해 언제든지 값을 추가 또는 삽입할 수 있다.


하지만 메모리 저장 구조상 어레이 리스트는 삽입과 삭제를 남발한다면 자원이 낭비될 수 있다.


만약 메모리에 ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ와 같이 저장되 있다고 할 때에


'ㅂ'자리에 자료를 추가한다면 뒤에 있는 자료를 하나씩 순서를 다 밀어줘야 하기 때문에 느려지게 된다.


ArrayList는 다양한 기능을 가지고 있는데 아래의 예제를 통해 확인해보자



package chap09.exam01.arrList;

import java.util.ArrayList;

public class ArrayList01 {

	public static void main(String[] args) {
		// ArrayList는 크기 지정을 할 필요가 없다.
//		ArrayList<String>list = new ArrayList<String>();
		// 방 크기를 지정한다면 메모리 공간 확보에 좋음
		ArrayList<String>list = new ArrayList<String>(3);
		list.add("collection"); // 0번 인덱스
		list.add("thread"); // 1번 인덱스
		list.add("java io"); //2번 인덱스
		list.add("network"); // 배열 같으면 예외가 발생
		list.add(3, "lambda"); // [3] = lambda, [4] = network로 밀림
		// bool값 반환은 값이 성공적으로 삽입됫다는 뜻
		
		
		// 크기 반환
		System.out.println(list.size());
		
		// 특정 인덱스의 값 확인
		System.out.println(list.get(3));
		System.out.println(list.get(4));
		
		System.out.println("--------------------------------");
		
		// for문을 이용하여 모든 값 출력
		for(int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
		System.out.println("--------------------------------");
		
		// 삭제하기
		// 중간의 인덱스 삭제 삽입은 메모리 사용에 비효율적이라 남발하는건 안좋음
		System.out.println(list.remove("thread"));
		System.out.println(list.size());
		System.out.println(list.remove(2));
		System.out.println(list.size());
		
	}

}
package chap09.exam01.arrList;

import java.util.ArrayList;
import java.util.Arrays;

public class ArrayList02 {

	// 배열의 값을 ArrayList로
	public static void main(String[] args) {
		// 배열
		String[] arr = {"list", "set", "map"};
		// array -> List : 조회는 되지만 변경은 불가능
		java.util.List<String> list = Arrays.asList(arr);
		System.out.println(list.size());
		System.out.println(list.get(1));
		
		// ArrayList.addAll은 Collection 타입을 인자로 받음
		// List -> ArrayList : 일괄적으로 List의 값을 ArrayList에 부어줌
		ArrayList<String> arrlist = new ArrayList<String>();
		arrlist.addAll(list);
		arrlist.add("collection");
		System.out.println();
		for(String item : arrlist) {
			System.out.println(item);
		}
		
	}

}
package chap09.exam01.arrList;

import java.util.ArrayList;

public class ArrayList03 {

	public static void main(String[] args) {
		ArrayList<Integer> score = new ArrayList<Integer>();
		
		score.add(70);  // 0
		score.add(80);  // 1
		score.add(50);  // 2
		score.add(90);  // 3
		score.add(100);// 4
		score.add(90);  // 5
		
		// 데이터 갯수 반환
		System.out.println(score.size() + "\n");
		// 데이터 수정 : 특정 인덱스의 값을 변경
		score.set(3, 95);
		System.out.println(score.get(3) + "\n");
		// 값 유무 확인 : 해당 값의 유무를 참/거짓으로 반환
		System.out.println(score.contains(30) + "\n");
		// 위치 확인
		System.out.println(score.indexOf(90) + "\n");
		// 비우기
		score.clear();
		// 비움상태 확인
		System.out.println(score.isEmpty());;
		System.out.println(score.size());

	}

}




2.LinkedList


링크드 리스트는 어레이 리스트와 매우 유사하다.


하지만 메모리 저장 방법이 어레이 리스트와 다르다.


자료마다 전에 저장한 자료, 다음 자료의 위치가 저장되고 어레이 리스트의 단점인 중간에 자료를 넣을 경우


앞의 자료와 뒤의 자료의 저장 위치만 살짝 수정하면 해결되기 때문에 훨씬 빠르다.


다음 예제를 직접 실행해보아 시간 차이를 확인해보자.



startTime = System.currentTimeMillis(); 을 통해서 작업 시작했을 때의 시간을 넣고


endTime = System.currentTimeMillis();을 통해서 작업이 끝났을 때의 시간을 넣는다.


그리고 endTime - startTime으로 시간 차를 비교하여 출력


Mill은 1초를 1000으로 나눈 값이다.

package chap09.exam02.linkList;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ListBenchMark {

	public static void main(String[] args) {

		// 선수 준비
		List<String> arr = new ArrayList<String>();
		List<String> link = new LinkedList<String>();
		// 조건
		for(int i = 1; i <= 100; i++) {
			arr.add("datadatadatadatadata");
			link.add("datadatadatadatadata");
		}
		// 초시계(걸린시간 = 도착시간 - 출발시간)
		long endTime = 0;
		long startTime = 0;

		// 측정  // 어떤 구현이든 구현에는 순서를 생각해 놓는게 중요
		/*ArrayList 체크*/
		// 타임워치 시작
		// 현재시간을 1/1000초로 환산
		startTime = System.currentTimeMillis();
		// 선수 달리기
		for(int i = 1; i < 1000000; i++) {
			// 중간에 넣는 실험
			// 뒤로 넣는 것을 시험하고 싶으면 index 값을 지운다.
			arr.add(55, "Add Data");
		}
		// 타임워치 스톱
		endTime = System.currentTimeMillis();
		// 결과 확인
		System.out.println("결과 : " + (endTime - startTime) + "mil");

		/*LinkedList 체크*/
		// 타임워치 시작
		// 현재시간을 1/1000초로 환산
		startTime = System.currentTimeMillis();
		// 선수 달리기
		for(int i = 1; i < 1000000; i++) {
			link.add(55, "Add Data");
		}
		// 타임워치 스톱
		endTime = System.currentTimeMillis();
		// 결과 확인
		System.out.println("결과 : " + (endTime - startTime) + "mil");
	}

}



'개념 및 코딩 > 07.Collection Framework' 카테고리의 다른 글

[JAVA]07-05.Stack, Queue  (0) 2018.09.04
[JAVA]07-04.HashMap, HashTable  (0) 2018.09.04
[JAVA]07-03.Hashset  (0) 2018.09.04
[JAVA]07-01.Collection, Map  (0) 2018.09.04

1.Collection Framework, Map (컬렉션 프레임워크, 맵)


컬렉션은 배열의 상위 버젼들이라고 생각하면 편하다.


아래와 같은 그림과 같이 Collection의 자식인 List Set Map이 있고 각자 특징과 사용처가 따로 있다.


전부 제네릭으로 타입을 정하여 원하는 자료형을 받아서 사용할 수 있다.



특징으로는 다음과 같다.


 인터페이스 분류

특징 

구현 클래스 

 Collection

List 

순서를 유지하고 저장

중복 저장 가능

ArrayList

Vector

LinkedList

Set

순서를 유지하지 않고 저장

중복 저장 안됨

HandSet

TreeSet 

 Map

키와 값의 쌍으로 저장

키는 중복 안 됨

값은 중복 저장 가능

HashMap

Hashtable

TreeMap

LinkedHashMap



처음 봤을때는 이해가 가지 않을거지만 뒤에 나오는 ArrayList부터 Hashtable


추가로 Stack과 Queue를 보고오면 이해가 갈 것이다.

'개념 및 코딩 > 07.Collection Framework' 카테고리의 다른 글

[JAVA]07-05.Stack, Queue  (0) 2018.09.04
[JAVA]07-04.HashMap, HashTable  (0) 2018.09.04
[JAVA]07-03.Hashset  (0) 2018.09.04
[JAVA]07-02.ArrayList, LinkedList  (0) 2018.09.04

1.Generic 메소드


메소드 안에서 객체화


package chap08.exam08.gmethod;

public class Gmethod {
	
	// 매개변수에 T 사용
	// 인자값의 타입에 따라 제너릭에 영향을 준다.
	// 들어오는 타입에 따라 대응이 된다.
	public <T> void method1(T t) {
		System.out.println("입력 값 : " + t);
	}
	
	// 받은 값을 그대로 반환
	public<T> T method2(T a) {
		return a;
	}
	
	// 매개변수를 이용한 반환타입 설정
	public <T> Box<T> method3(T t){ // 1. 100이 들어온다.
													// 2. T의 타입이 Integer가 된다.
		Box<T> box = new Box<T>();   // Integer 형태로 객체화
													// 객체에 100이 들어간다.
		box.setValue(t);
		return box;								// 이 객체를 반환 한다.
	}
}
package chap08.exam08.gmethod;

public class Box<T> {
	// 아직 뭔지는 모르나 어떤 타입이 설정 될 예정
	// 타입이 설정되면 클래스 모든 타입이 통일 된다.
	// 클래스 선언/객체화 될 때 타입을 설정함.
	// T 자리에는 쓰고싶은거 써도 됨
	private T value;

	public T getValue() {
		return value;
	}

	public void setValue(T value) {
		this.value = value;
	}
}
package chap08.exam08.gmethod;

public class Main {

	public static void main(String[] args) {
		Gmethod test = new Gmethod();
		
		test.method1("ㅎㅇ");
		
		String str = test.method2("고길동 재산 : ");
		int money = test.method2(Integer.MAX_VALUE);
		System.out.println(str + money);
		
		Box<Integer> box1 = test.method3(100);
		System.out.println(box1.getValue());
		Box<String> box2 = test.method3("hong");
		System.out.println(box2.getValue());
		
		// Method의 return type과 Reference type이
		// 상황에 따라 유연하게 변경가능
	}

}






2.Generic 상속


Generic 역시 상속이 가능하다.



package chap08.exam09.inheritance; public class BasicInfo <N, A> { private N name; private A age; public N getName() { return name; } public void setName(N name) { this.name = name; } public A getAge() { return age; } public void setAge(A age) { this.age = age; } }

package chap08.exam09.inheritance;

public class DetailInfo<N, A, H> extends BasicInfo<N, A> {
	private H hobby;

	public H getHobby() {
		return hobby;
	}

	public void setHobby(H hobby) {
		this.hobby = hobby;
	}
	
}
package chap08.exam09.inheritance;

public class Main {

	public static void main(String[] args) {
		//
		DetailInfo<String, Integer, String> info = new DetailInfo<String, Integer, String>();
		
		info.setName("둘리");
		info.setAge(56);
		info.setHobby("호잇");
		
		System.out.println(info.getName() + ", 나이는 " + info.getAge() + "\n" + "취미는 " + info.getHobby());
	}

}



'개념 및 코딩 > 06.기타' 카테고리의 다른 글

[JAVA]06-06.Generic  (0) 2018.09.03
[JAVA]06-05.Object  (0) 2018.09.03
[JAVA]06-04.String  (0) 2018.09.03
[JAVA]06-03.Throw 예외처리, 커스텀 예외처리  (0) 2018.09.03
[JAVA]06-02.예외처리 instance of, try catch  (0) 2018.09.03

+ Recent posts