반응형
목차
스레드
- 병렬 처리가 필요한 작업에서 유용
- 스레드 생성
- 인터페이스
- 구현 클래스
class MyRunnable implements Runnable { public void run() { System.out.println("Runnable 구현 클래스 스레드 실행!"); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
- 익명 객체
public class Main { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { public void run() { System.out.println("Runnable 익명 객체 스레드 실행!"); } }); thread.start(); } }
- 상속
- 상속 클래스
class MyThread extends Thread { public void run() { System.out.println("Thread 상속 클래스 스레드 실행!"); } } public class Main { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } }
- 익명 객체
public class Main { public static void main(String[] args) { Thread thread = new Thread() { public void run() { System.out.println("Thread 익명 객체 스레드 실행!"); } }; thread.start(); } }
- 인터페이스
- 익명 함수로 생성
- Runnalbe을 상속받아 run()함수 안에서 병렬로 수행
- start()로 실행 시 run함수 수행
// 메인 스레드가 동시에 두 가지를 모두 처리 X
package ch14.sec03.exam01;
import java.awt.Toolkit;
public class BeepPrintExample {
public static void main(String[] args) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i = 0; i<5;i++) {
toolkit.beep();
}
try {
Thread.sleep(500);
}catch(Exception e) { }
for(int i=0;i<5;i++) {
System.out.println("띵");
try {
Thread.sleep(500);
}catch(Exception e) { }
}
}
}
출력 결과
(0.5초 간격으로 비프음)
(0.5초 간격으로)
띵
띵
띵
띵
띵
// 2개를 동시에 처리하여 소리와 문구가 같이 나옴
package ch14.sec03.exam02;
import java.awt.Toolkit;
public class BeepPrintExample {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i = 0; i<5;i++) {
toolkit.beep();
}
try {
Thread.sleep(500);
}catch(Exception e) { }
}
});
thread.start();
for(int i=0;i<5;i++) {
System.out.println("띵");
try {
Thread.sleep(500);
}catch(Exception e) { }
}
}
}
출력 결과
(0.5초 간격으로 비프음과 함께)
띵
띵
띵
띵
띵
- Thread 익명 자식 클래스로 생성할 수 있음
package ch14.sec03.exam02;
import java.awt.Toolkit;
public class BeepPrintExample {
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i = 0; i<5;i++) {
toolkit.beep();
}
try {
Thread.sleep(500);
}catch(Exception e) { }
}
};
thread.start();
for(int i=0;i<5;i++) {
System.out.println("띵");
try {
Thread.sleep(500);
}catch(Exception e) { }
}
}
}
- setName(스레드 이름)을 통해 사용자 지정 이름을 만들 수 있다.
- getName(스레드 이름)을 통해 스레드의 이름을 가져올 수 있다.
- 스레드의 상태
- start()
- 시작
- sleep()
- 대기
- join()
- 일시 정지
- 주어진 시간 후 실행
package ch14.sec05.exam02; public class SumThread extends Thread{ private long sum; public long getSum() { return sum; } public void setSum(long sum) { this.sum = sum; } @Override public void run() { for(int i=1; i<=100; i++) { sum += i; } } } package ch14.sec05.exam02; public class JoinExample { public static void main(String args[]) { SumThread sumThread = new SumThread(); sumThread.start(); try { sumThread.join(); }catch(InterruptedException e) { } System.out.println("1~100 합: "+ sumThread.getSum()); } } 출력 결과 계산이 모두 끝난 후 1~100 합: 5050 출력
- wait()
- 일시 정지
- interrupt()
- 일시 정지일 경우 InterruptedException 발생
- notify()
- wait() 상태를 대기 상태로 만듬
- notifyAll()
- 모든 스레드를 깨움
- yield()
- 실행 상태에서 다른 스레드에게 실행을 양보하고 대기 상태
- 무의미한 반복 속에서 스레드가 돈다면 의미가 없음
- 대기 상태로 돌리고 다른 스레드에게 양보
package ch14.sec05.exam03; public class WorkThread extends Thread{ public boolean work = true; public WorkThread(String name) { setName(name); } @Override public void run() { while(true) { if(work) { System.out.println(getName() + ": 작업처리"); } else { Thread.yield(); } } } } package ch14.sec05.exam03; public class YieldExample { public static void main(String args[]) { WorkThread workThreadA = new WorkThread("workThreadA"); WorkThread workThreadB = new WorkThread("workThreadB"); workThreadA.start(); workThreadB.start(); try { Thread.sleep(5000); }catch(InterruptedException e) { workThreadA.work = false; } try { Thread.sleep(10000); }catch(InterruptedException e) { workThreadB.work = true; } } } 출력 결과 workThreadB: 작업처리 workThreadB: 작업처리 workThreadB: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리 workThreadA: 작업처리
- start()
스레드 동기화
- 하나의 객체를 공유하여 작업할 때, 동시성 제어가 필요
- ≠ 트랜잭션
- 등록이 아닌, 조회에 해당하므로 트랜잭션과는 무관하다.
- 동기화 메서드 선언
- 메서드 앞에 synchronized 선언
- 실행 시 객체는 잠금이 일어나고, 실행이 끝나면 잠금이 풀린다.
- 일부 영역을 실행할 때만 객체의 잠금을 걸 수도 있다.
package ch14.sec06.exam01; public class Calculator { private int memory; public int getMemory() { return memory; } public synchronized void setMemory1(int memory) { // 동기화 메소드 this.memory = memory; try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + ": " + this.memory); } public void setMemory2(int memory) { // 동기화 블록 synchronized (this) { this.memory = memory; try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + ": " + this.memory); } } } package ch14.sec06.exam01; public class User1Thread extends Thread { private Calculator calculator; public User1Thread() { setName("User1Thread"); } public void setCalculator(Calculator calculator) { this.calculator = calculator; } @Override public void run() { calculator.setMemory1(100); } } package ch14.sec06.exam01; public class User2Thread extends Thread { private Calculator calculator; public User2Thread() { setName("User2Thread"); } public void setCalculator(Calculator calculator) { this.calculator = calculator; } @Override public void run() { calculator.setMemory2(50); } } package ch14.sec06.exam01; public class SynchronizedExample { public static void main(String[] args) { Calculator calculator = new Calculator(); User1Thread user1Thread = new User1Thread(); user1Thread.setCalculator(calculator); user1Thread.start(); User2Thread user2Thread = new User2Thread(); user2Thread.setCalculator(calculator); user2Thread.start(); } } 출력 결과 User1Thread: 100 User2Thread: 50
- 동기화 하지 않을 경우 calculator를 동시에 접근하게 된다.
package ch14.sec06.exam01; public class Calculator { private int memory; public int getMemory() { return memory; } public void setMemory1(int memory) { // 동기화 메소드 this.memory = memory; try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + ": " + this.memory); } public void setMemory2(int memory) { // 동기화 블록 synchronized (this) { this.memory = memory; try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + ": " + this.memory); } } } 출력 결과 User2Thread: 50 User1Thread: 50
스레드 제어
- 정확한 교대 작업이 필요할 경우 자신의 작업이 끝나면 상대방 스레드를 일시 정지 상태에서 풀어주고 자신을 일시정지로 만들면 됨
- notify()
- 한 스레드가 작업 완료시 호출하여 일시 정지 상태에 있는 다른 스레드를 실행 대기 상태로 만듬
- notifyAll()
- 모든 스레드를 대기 상태로
- wait()
- 자신을 일시 정지 상태로 만듬
- 동기화 블록, 동기화 메소드 내에서만 사용 가능
- interrupt()
- 스레드가 일시 정지 상태에 있을 때 InterruptedException예외를 발생
- 예외 처리를 통해 메소드 정상 종료
스레드 풀
- 병렬 작업 증가로 인한 스레드의 폭증을 막기 위해 사용
- 작업 처리에 사용되는 스레드를 제한된 개수만큼 정해 놓고 작업 큐에 들어오는 작업들을 스레드가 하나씩 맡아 처리하는 방식
- 작업 처리가 끝난 스레드는 다시 작업 큐에서 새로운 작업을 가져와 처리
- 스레드의 개수가 늘어나지 않아 성능 저하 방지
컬렉션 프레임워크
- Set
- 중복 허용
- Map
- 중복을 허용하지 않음
- List
- ArrayList
List 컬렉션
- ArrayList보다는 LinkedList가 빠르다.
- ArrayList를 주로 쓴다.
- 주요 메서드
- add(값)
- 값 추가
- set(인덱스, 값)
- 해당 인덱스 위치의 값을 매개 변수 값으로 바꿈
- contains(값)
- 값 존재 여부 확인
- get(인덱스)
- 해당 위치의 값 확인
- isEmpty()
- 비어있는 여부
- size()
- 리스트의 크기
- clear()
- 리스트 비우기
- remove(인덱스)
- 해당 인덱스 값 삭제
- add(값)
ArrayList
- 내부 배열을 저장
package ch15.sec02.exam01;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@AllArgsConstructor
@ToString
public class Board {
private String subject;
private String content;
private String writer;
}
package ch15.sec02.exam01;
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
List<Board> list = new ArrayList<>();
list.add(new Board("제목1", "내용1", "글쓴이1"));
list.add(new Board("제목2", "내용2", "글쓴이2"));
list.add(new Board("제목3", "내용3", "글쓴이3"));
list.add(new Board("제목4", "내용4", "글쓴이4"));
list.add(new Board("제목5", "내용5", "글쓴이5"));
int size = list.size();
System.out.println("총 객체 수: " + size);
System.out.println();
Board board = list.get(2);
System.out.println(board.getSubject() + "\\t" + board.getContent() + "\\t" + board.getWriter());
System.out.println();
for (int i = 0; i < list.size(); i++) {
Board b = list.get(i);
System.out.println(b.getSubject() + "\\t" + b.getContent() + "\\t" + b.getWriter());
}
System.out.println();
list.remove(2);
list.remove(2);
for (Board b : list) {
System.out.println(b.getSubject() + "\\t" + b.getContent() + "\\t" + b.getWriter());
}
System.out.println();
for (Board b : list) {
System.out.println(b);
}
System.out.println();
list.stream().forEach(b -> System.out.println(b));
}
}
출력 결과
총 객체 수: 5
제목3 내용3 글쓴이3
제목1 내용1 글쓴이1
제목2 내용2 글쓴이2
제목3 내용3 글쓴이3
제목4 내용4 글쓴이4
제목5 내용5 글쓴이5
제목1 내용1 글쓴이1
제목2 내용2 글쓴이2
제목5 내용5 글쓴이5
Board(subject=제목1, content=내용1, writer=글쓴이1)
Board(subject=제목2, content=내용2, writer=글쓴이2)
Board(subject=제목5, content=내용5, writer=글쓴이5)
Board(subject=제목1, content=내용1, writer=글쓴이1)
Board(subject=제목2, content=내용2, writer=글쓴이2)
Board(subject=제목5, content=내용5, writer=글쓴이5)
Vector
- ArrayList와 내부 구조 같음
- 동기화된 메소드로 구성되어 있어 멀티스레드가 동시에 Vector() 메소드를 실행할 수 없다.
LinkedList
- ArrayList와 사용 방법은 동일하지만 내부 구조가 다르다.
- ArrayList는 내부 배열에 객체를 저장하지만, LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.
package ch15.sec02.exam3;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LinkedListExam {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new LinkedList<String>();
long startTime;
long endTime;
startTime = System.nanoTime();
for(int i=0;i<10000;i++) {
list1.add(0,String.valueOf(i));
}
endTime = System.nanoTime();
long totalTime1 = endTime - startTime;
System.out.printf("%-17s %8d ns \\n", "ArrayList 걸린 시간: ",(endTime-startTime));
startTime = System.nanoTime();
for(int i=0;i<10000;i++) {
list2.add(0,String.valueOf(i));
}
endTime = System.nanoTime();
long totalTime2 = endTime - startTime;
System.out.printf("%-17s %8d ns \\n", "LinkedList 걸린 시간: ",(endTime-startTime));
System.out.println("ArrayList가 " + totalTime1 / totalTime2 + "배 빠름");
startTime = System.nanoTime();
for(int i=0;i<10000;i++) {
list1.get(i);
}
endTime = System.nanoTime();
long totalTime3 = endTime - startTime;
System.out.printf("%-17s %8d ns \\n", "ArrayList 걸린 시간: ",(endTime-startTime));
startTime = System.nanoTime();
for(int i=0;i<10000;i++) {
list2.get(i);
}
endTime = System.nanoTime();
long totalTime4 = endTime - startTime;
System.out.printf("%-17s %8d ns \\n", "LinkedList 걸린 시간: ",(endTime-startTime));
System.out.println("LinkedList가 " + totalTime4 / totalTime3 + "배 빠름");
}
}
출력 결과
ArrayList 걸린 시간: 5705400 ns
LinkedList 걸린 시간: 762300 ns
ArrayList가 7배 빠름
ArrayList 걸린 시간: 321900 ns
LinkedList 걸린 시간: 38607200 ns
LinkedList가 119배 빠름
Set
- Set은 저장 순서가 유지되지 않음
- 객체를 중복해서 저장할 수 없음
- 하나의 null만 저장 가능
- HashSet
- 가장 많이 사용되는 Set 컬렉션
- Set 컬렉션은 index로 객체를 가저올 수 없다.
- 1개씩 가져와야 하므로 향상된 for문이나 interator를 사용한다.
package ch15.sec03.exam3;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetExmaple {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("Java");
set.add("JDBC");
set.add("JDBC");
set.add("JPA");
set.add("Spring");
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
if(element.equals("JSP")) {
iterator.remove();
}
}
System.out.println();
set.remove("JDBC");
for(String element : set) {
System.out.println(element);
}
}
}
출력 결과
Java
JDBC
JPA
Spring
Java
JPA
Spring
Map
- key와 value값이 존재
- key값을 이용하여 value값을 가져올 수 있음
- key는 중복되지 않는다.
- 인덱스로 찾는 것보다 key로 찾는 Hash가 더 빠르다.
- LinkedHashMap은 들어간 순서대로 저장
- 주요 함수
- put(key, value)
- key 값을 이용하여 value값 저장
- get(key)
- key 값을 이용하여 value값을 가져옴
- containsKey(key)
- key 값의 존재 여부 반환
- containsValue(value)
- value 값의 존재 여부 반환
- entrySet()
- 모든 Key, value 객체를 Set에 담아서 리턴
- 반복을 시켜야 할 때 사용
- keySet()
- 모든 키 값을 Set에 담아 리턴
- 반복을 시켜야 할 때 사용
- values()
- 저장된 모든 값 Collection에 담아 리턴
- remove(), clear(), size() 등은 List와 같음
- put(key, value)
- 대부분 중복이 가능하면 put, 그렇지 않으면 add를 쓰는 경향이 있다.
package ch15.sec04.exam01;
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
String[] names = {"홍길동","김길동","최길동","홍영수"};
Map<String, Integer> map = new HashMap<String, Integer>();
// getOrDefaut 있으면 넣고, 없으면 Default값으로 지정
for( String n : names) {
map.put(String.valueOf(n.charAt(0)), map.getOrDefault(String.valueOf(n.charAt(0)), 0)+1);
}
System.out.println(map);
}
}
**출력 결과**
{김=1, 최=1, 홍=2}
package ch15.sec04.exam01;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("신용권", 85);
map.put("홍길동", 90);
map.put("동장군", 80);
map.put("홍길동", 95);
System.out.println("총 Entry 수: " + map.size());
System.out.println(map);
System.out.println();
String key = "홍길동";
int value = map.get(key);
System.out.println(key + ": " + value);
System.out.println();
Set<String> keySet = map.keySet();
Iterator<String> keyIterator = keySet.iterator();
while(keyIterator.hasNext()){
String k = keyIterator.next();
Integer v = map.get(k);
System.out.println(k+ ": "+ v);
}
System.out.println();
Set<Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Entry<String, Integer>> entryIterator = entrySet.iterator();
while(entryIterator.hasNext()) {
Entry<String,Integer> entry = entryIterator.next();
String k = entry.getKey();
Integer v = entry.getValue();
System.out.println(k+": "+v);
}
System.out.println();
map.remove("홍길동");
System.out.println("총 Entry 수: "+map.size());
System.out.println();
for(Integer v : map.values()) {
System.out.println(v);
}
}
}
**출력 결과**
총 Entry 수: 3
{홍길동=95, 신용권=85, 동장군=80}
홍길동: 95
홍길동: 95
신용권: 85
동장군: 80
홍길동: 95
신용권: 85
동장군: 80
총 Entry 수: 2
85
80
Properties
- 키와 값이 = 기호로 연결되어 있는 텍스트 파일을 읽을 수 있다.
package ch15.sec04.exam03;
import java.util.Properties;
import java.util.ResourceBundle;
public class PropertiesExample {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.load(PropertiesExample.class.getResourceAsStream("database.properties"));
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
String admin = prop.getProperty("admin");
System.out.println("driver:"+driver);
System.out.println("url:"+url);
System.out.println("username:"+username);
System.out.println("password:"+password);
System.out.println("admin:"+admin);
System.out.println("-------------------------------------------------");
ResourceBundle rb = ResourceBundle.getBundle("database"); // 이 방법도 가능
}
}
TreeSet
- 이진 트리를 기반으로 한 Set 컬렉션
- 노드가 연결된 구조
- 객체를 저장하면 정렬된다.
TreeMap
- TreeSet과 비슷하며 Map을 저장
- 키를 기준으로 자동 정렬
Comparable과 Comparator
- 사용자 정의 객체 정렬에 사용
- 메서드는 CompareTo메서드를 오버라이딩
- compareTo(T o)
- 주어진 객체와 같으면 0리턴
- 적으면 음수 리턴
- 크면 양수 리턴
Stack
- 후입선출
- 나중에 넣은 객체가 먼저 빠져나옴
- 주요 함수
- push(E item)
- 뒤쪽에 아이템 삽입
- pop()
- 가장 뒤쪽 아이템 제거
- push(E item)
package ch15.sec06.exam01;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
public class Coin {
private int value;
}
package ch15.sec06.exam01;
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Coin> coinBox = new Stack<Coin>();
coinBox.push(new Coin(100));
coinBox.push(new Coin(50));
coinBox.push(new Coin(500));
coinBox.push(new Coin(10));
while(!coinBox.isEmpty()) {
Coin coin = coinBox.pop();
System.out.println("꺼내온 동전 :" + coin.getValue() + "원");
}
}
}
출력 결과
꺼내온 동전 :10원
꺼내온 동전 :500원
꺼내온 동전 :50원
꺼내온 동전 :100원
Queue
- 선입선출
- 먼저 들어간 객체가 먼저 나옴
- new LinkedList<>로 선언해야 함
- 주요 함수
- offer(E e)
- 뒤쪽에 아이템 삽입
- poll()
- 가장 앞쪽 아이템 제거
- offer(E e)
package ch15.sec06.exam02;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Message {
public String command;
public String to;
}
package ch15.sec06.exam02;
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<Message> messageQueue = new LinkedList<>();
messageQueue.offer(new Message("sendMail", "홍길동"));
messageQueue.offer(new Message("sendSMS", "신용권"));
messageQueue.offer(new Message("sendKakaotalk", "김자바"));
while(!messageQueue.isEmpty()) {
Message message = messageQueue.poll();
switch(message.command) {
case "sendMail":
System.out.println(message.to + "님에게 메일을 보냅니다.");
break;
case "sendSMS":
System.out.println(message.to + "님에게 SMS를 보냅니다.");
break;
case "sendKakaotalk":
System.out.println(message.to + "님에게 카카오톡을 보냅니다.");
break;
}
}
}
}
출력 결과
홍길동님에게 메일을 보냅니다.
신용권님에게 SMS를 보냅니다.
김자바님에게 카카오톡을 보냅니다.
메모
- ArrayList, HashMap이 가장 많이 쓰임
- Iterator를 사용하면 Iterator타입의 객체가 나온다.
- 주요 함수
- hasNext()
- 다음 객체 존재 여부를 반환
- next()
- 다음 객체를 반환
- remove()
- 가져온 객체를 컬렉션에서 제거
- hasNext()
- 주요 함수
- JSON
- JS
- 배열 → [ ]
- 객체 → { }
- Python
- 리스트 → [ ]
- 딕셔너리 → { }
- 자바
- 리스트 → [ ]
- 맵→ { }
- JS
- [JSON] JSON 이란 무엇인가? 간단 정리 및 예제를 통한 사용 방법
[JSON] JSON 이란 무엇인가? 간단 정리 및 예제를 통한 사용 방법
JSON 이란? JSON은 JavaScript Object Notation 의 약자입니다. 직역하면 '자바 스크립트 객체 표기법'으로 데이터를 쉽게 ' 교 환 ' 하고 ' 저 장 ' 하기 위한 텍스트 기반의 데이터 교환 표준 입니다. JSON은
codingazua.tistory.com
728x90
반응형
'Java' 카테고리의 다른 글
4/15 - 스트림, 데이터와 입출력 (0) | 2025.04.19 |
---|---|
4/14 - 컬렉션 자료 구조, 람다 (0) | 2025.04.19 |
4/9 - 라이브러리와 모듈, 예외 처리, java.base 모듈 (1) (1) | 2025.04.12 |
4/8 - 상속, 인터페이스, 중첩 선언과 익명 객체 (0) | 2025.04.12 |
4/7 - 클래스 (1) | 2025.04.12 |