Programming/Java
스트림, IO Stream, 직렬화(Serializable), 역직렬화(Deserializable), 스레드
김심슨
2025. 6. 11. 10:49
스트림 https://ryuzyproject.tistory.com/169
스트림
1. 스트림스트림(Stream)은 자바 8에서 도입된 기능으로, 컬렉션이나 배열의 데이터를 반복문 없이 함수형 스타일로 처리할 수 있도록 도와주는 도구입니다. 스트림은 데이터 저장소가 아니라, 데
ryuzyproject.tistory.com
package lesson08;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Ex01_Main {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("apple", "banana", "orange", "apple");
System.out.println(fruits);
/*
String :: toUpperCase
- 메서드 참조
- s -> s.toUpperCase()와 같은 람다식을 더 간단하게 표현
- String 클래스의 toUpperCase() 인스턴스 메서드를 현재 스트림의 각 요소에 대해 호출하겠다는 뜻
*/
fruits.stream()
// a로 시작하는 걸 찾아내서 stream 객체로 반환
.filter(f -> f.startsWith("a"))
// 대문자로 바꿔서 반환하세요 (중간연산, 아직 안꺼냄)
.map(String::toUpperCase)
// 중복 제거
.distinct()
// 반복하면서 찍어줘!
.forEach(System.out::println); // APPLE
}
}
package lesson08;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Ex03_Main {
public static void main(String[] args) {
try (
FileReader reader = new FileReader("src/input.txt");
FileWriter writer = new FileWriter("output2.txt");
) {
int ch;
while((ch=reader.read())!= -1) {
writer.write(ch);
}
System.out.println("파일 복사 완료(문자 스트림)");
}catch (IOException e) {
e.printStackTrace();
}
}
}
https://ryuzyproject.tistory.com/170?category=1210552
스레드
1. 스레드스레드(Thread)는 하나의 프로세스 내에서 독립적으로 실행되는 실행 흐름 단위를 말합니다. 일반적으로 하나의 프로그램(프로세스)은 하나 이상의 스레드를 가질 수 있으며, 이를 통해
ryuzyproject.tistory.com
종합 예제 : 점원별 햄버거 만들기
package lesson08;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
class Ex14_Order {
private final int orderId;
public Ex14_Order(int orderId) {
this.orderId = orderId; //id 번호를 받아다가 저장해 줄 생성자
}
public int getOrderId() {
return orderId;
}
}
//Callable을 class로 구현해서 사용하기 (Runnable을 이용하면 return하지 못하기 때문)
class OrderProcessor implements Callable<String> {
private final Ex14_Order order;
private final String workerName;
private static final Random random = new Random();
private static final Map<String, int[] > workerSpeedMap = Map.of(
"김사과",new int[] {1000,2000}, //숫자가 작을수록 빨라용~
"반하나",new int[] {2000,3000},
"오렌지",new int[] {3000,4000}
);
private static final AtomicInteger totalProcessed = new AtomicInteger(0); //고전적인 방법으로 멀티스레스방법에서 값을 수정할 때 동시다발적으로 일어날 수 있으니까 싱크로나이즈를 썼었음. 근데 AtomicInteger은 멀티 스레드일 때 값을 알아서 충돌나지 않게 해준다. 값을 더하거나 빼거나 연산을 할 때 이 객체에 있는 값은 멀티스레드 환경에서 충돌나지 않음
private static final AtomicInteger processed = new AtomicInteger(0);
private static final Map<String, Integer> workerStats = new ConcurrentHashMap<>();
//맵을 쓰는데 스레드에 안정된 클래스
public OrderProcessor(Ex14_Order order, String workerName) {
this.order = order;
this.workerName = workerName;
}
@Override
public String call() throws Exception {
int[] speedRange = workerSpeedMap.get(workerName);
int prepTime = random.nextInt(speedRange[1] - speedRange[0] + 1) + speedRange[0];
Thread.sleep(prepTime);
// 주문 1건이 처리되었으니, 전체 주문 수를 1 증가시켜라
totalProcessed.incrementAndGet();
// workerName : 아르바이트생 이름
// 1 : 처리한 주문 수
// 알바생 이름이 Map에 없으면 (workerName, 1)로 추가
// 이미 있다면 ("김사과", 기존값+1)로 업데이트 해줘! (Integer::sum)
workerStats.merge(workerName,1, Integer::sum );
return workerName + " - 주문 " + order.getOrderId() + " 번 완료 (소요시간 : " + prepTime + "ms)";
}
public static int getTotalProcessed() {
return totalProcessed.get();
}
public static void printStats() {
System.out.println("점원별 처리 주문 수");
workerStats.forEach((name,count)-> System.out.println(name + " : " + count + "건"));
}
}
public class Ex14_Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
int totalOrders = 10; //전체 주문이 10개
List<String> workers = List.of("김사과", "반하나", "오렌지");
ExecutorService executor = Executors.newFixedThreadPool(workers.size());
List<Future<String>> futures = new ArrayList<>(); //리턴 받을 Future을 만든다! 배열에 저장
for (int i = 0; i < totalOrders; i++) {
String worker = workers.get(i % workers.size()); //리턴된 걸 가져오는데, 사이즈만큼 나눌 것.
Ex14_Order order = new Ex14_Order(i);
futures.add(executor.submit(new OrderProcessor(order, worker)));
// futures에 결과값들이 쌓일 것
}
for (Future<String> future : futures) {
System.out.println(future.get());
}
executor.shutdown();
OrderProcessor.printStats();
System.out.println("총 주문 처리 수 : " + OrderProcessor.getTotalProcessed() + "건");
}
}
-------------------------------------------------------
"C:\Program Files\Java\jdk-17\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1.1.1\lib\idea_rt.jar=51877" -Dfile.encoding=UTF-8 -classpath C:\ai_lsb\Java\programming\out\production\programming lesson08.Ex14_Main
김사과 - 주문 0 번 완료 (소요시간 : 1382ms)
반하나 - 주문 1 번 완료 (소요시간 : 2793ms)
오렌지 - 주문 2 번 완료 (소요시간 : 3113ms)
김사과 - 주문 3 번 완료 (소요시간 : 1011ms)
반하나 - 주문 4 번 완료 (소요시간 : 2572ms)
오렌지 - 주문 5 번 완료 (소요시간 : 3314ms)
김사과 - 주문 6 번 완료 (소요시간 : 1347ms)
반하나 - 주문 7 번 완료 (소요시간 : 2059ms)
오렌지 - 주문 8 번 완료 (소요시간 : 3717ms)
김사과 - 주문 9 번 완료 (소요시간 : 1019ms)
점원별 처리 주문 수
반하나 : 3건
김사과 : 4건
오렌지 : 3건
총 주문 처리 수 : 10건
종료 코드 0(으)로 완료된 프로세스