- 강의
- 59강(Server-client 소개와 직렬화/역직렬화) ~ 63강(멀티 쓰레딩 프로그래밍)
- 실습 코드 : https://github.com/kung036/java_task/tree/test/src/practice/day20240516
신입 개발자에게 원하는 것
- 돌아가는 판의 흐름을 읽고 이해하기
- 돌아가는 판
- 다양한 자바 프레임워크
- 다양한 자바 라이브러리
- 복잡하고 많은 코드
- 실무를 위해 익혀야 하는 기술과 지식
- 자바
- AOP
- clean code
- optimizing
- 디자인 패턴
- spring
- lombok
- jcoco
- mockito
- 자바
- 회사 실무 코드의 흐름을 일기 위해서 → 모든 프레임워크, 라이브버리, 고급 기술을 익힐 필요 X
- 자주 사용하는 일부분만 알아도 됨
메소드 레퍼런스
- 자바 함수 가독성 진화
- 일반 함수 → 람다식 → 메소드 레퍼런스
- Java 8 이후 지원
- 메서드를 참조해서 해당 메소드의 동작을 다른 코드엥서 재사용할 수 있는 기능
- 호출 : Class::MethodName
Consumer<String> func = text -> System.out.println(text); // 람다식 Consumer<String> func = System.out::println; // 메소드 레퍼런스
- 자주 사용되는 함수형 인터페이스
함수형 인터페이스 | 파라미터 타입 | 반환 타입 | 추상 메서드 이름 | 설명 |
Supplier | 없음 | T | get | T 타입 값 제공 |
Consumer | T | void | accept | T 타입 값 소비 |
Function<T,R> | T | R | apply | T 타입 인자 받음 |
BiFunction<T,U,R> | T,U | R | apply | T와 U타입 인자 받음 |
Predicate | T | boolean | test | Boolean값 반환 |
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
- 방법
- static 메서드 참조 : Class::statidMethod
- 생성자 참조 : Class:new
- Supplier 인터페이스에 자주 사용됨
- 객체 인스턴스 메소드 참조 : instance::method
- 임의 인스턴스 메소드 참조 : Class::method → 객체 인스턴스 메서드처럼 동작
- 코드
public class MethodReferenceTest1 {
public static void main(String[] args) {
// static method
Consumer<String> ex1 = (str) -> Printer.printSomething(str); // Lambda Expression
Consumer<String> ex2 = Printer::printSomething; // Method Reference
ex1.accept("Lamda 식 사용"); // Lamda 식 사용를 출력합니다.
ex1.accept("메서드 레퍼런스 사용"); // 메서드 레퍼런스 사용를 출력합니다.
// 생성자 호출
Supplier<Customer> ex3 = () -> new Customer(); // Lambda Expression
Supplier<Customer> ex4 = Customer::new; // Method Reference
System.out.println(ex3.get()); // Customer [name=홍길동]
System.out.println(ex4.get()); // Customer [name=홍길동]
Function<String, Customer> ex5 = (name) -> new Customer(name); // Lambda Expression
Function<String, Customer> ex6 = Customer::new; // Method Reference
System.out.println(ex5.apply("홍길동")); // Customer [name=홍길동]
System.out.println(ex6.apply("홍길동")); // Customer [name=홍길동]
// Instance method 참조
Customer customer = new Customer("임한별");
Customer customer1 = new Customer("이지은");
Supplier<String> ex7 = customer::toString; // Lambda Expression
Supplier<String> ex8 = customer1::toString; // Method Reference
System.out.println(ex7.get()); // Customer [name=임한별]
System.out.println(ex8.get()); // Customer [name=이지은]
// 임의 인스턴스 method 참조
List<Customer> customerList = Arrays.asList(
new Customer("임한별"),
new Customer("이지은"),
new Customer("박하나"),
new Customer("김창조")
);
customerList.forEach(Customer::printInfo);
/*
Customer [name=임한별]
Customer [name=이지은]
Customer [name=박하나]
Customer [name=김창조]
*/
}
}
- 사용
- static method 참조 : stream의 filter, forEach 등
- 생성자 참조 : stream의 map 등
- 객체 인스턴스 메소드 참조 : stream의 filter 등
- 임의 인스턴스 메서드 참조 : stream의 map, forEach 등
- 사용 이유
- 가독성 ↑
- 취향에 따라서 선택 사용 가능
멀티 쓰레딩 프로그래밍
Thread
- 프로세스 내 동시에 동작하는 작업 단위
- 사용 이유
- 병렬 처리
- 속도 증가
- java의 Thread
- main thread에서 시작
- 작업 순서
- thread 객체 생성(NEW) → 실행 대기(Runnable) → 실행 → 종료(Terminated)
- 실행 대기와 실행을 반복함
- Runnable 함수형 인터페이스를 상속받아서 구현 및 사용
- 코드 예시
- 동작 순서는 항상 다를 수 있음
public class Threading {
public static void main(String[] args) {
// thread 실행
Thread thread = new Thread(new MyThread());
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread >> " + Thread.currentThread().getName() + " is running");
}
});
Thread thread2 = new Thread(() -> System.out.println("Thread >> " + Thread.currentThread().getName() + " is running"));
System.out.println("Thread >> " + Thread.currentThread().getName() + " is running");
// Thread >> main is running
// 동작 시작
thread.start(); // Thread >> Thread-0 is running
thread1.start(); // Thread >> Thread-1 is running
thread2.start(); // Thread >> Thread-2 is running
}
static class MyThread implements Runnable {
@Override
public void run() {
System.out.println("Thread >> " + Thread.currentThread().getName() + " is running");
}
}
}
멀티 쓰레딩 프로그래밍(Multi Thread Programming)
- 자바의 멀티 쓰레딩 프로그래밍 : 여러 쓰레드가 번갈아가면서 동작함
- 멀티 쓰레딩 프로그래밍 코드
public class MultiThreading {
public static void main(String[] args) {
// Q) 1 ~ 100 까지 숫자를 출력하는데, Multi Thread를 사용해서 일 분담
// A) 2명 Thread 사용
Thread thread1 = new Thread(new PrintNumberRunnable(1, 50));
Thread thread2 = new Thread(new PrintNumberRunnable(51, 100));
thread1.start();
thread2.start();
// 51 1 52 53 2 54 3 55 4 56 5 57 6 7 8 9 58 59 10 60 61 11 62 12 63 13 64 14 65 15 66 16 67 17 18 19 20 68 69 70 71 72 73 21 22 74 75 23 76 24 25 26 27 28 29 30 31 32 33 77 34 78 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
// 두 개의 thread가 동시에 진행되서 숫자가 정렬되어 있지 않음
}
}
- 주의할 점
- thread 들의 순서는 보장 X
- thread 들은 각자의 개별 영역이 있고, 공통 영역인 method area, heap area 존재
- 문제점
- thread들이 공통 영역을 동시에 접근하여 수정할 때 일관성 및 충돌 문제 발생
- 해결방법
- thread 동작이 끝날 때까지 다른 thread들 동작 X → 동작 완료 후 다른 thread 동작 가능
- Synchronized(동기화) 키워드 이용
- Synchronized 코드
public class MultiThreadingIssue {
public static void main(String[] args) {
Counter counter = new Counter(); // heap(공통 영역)에 new Counter가 생성되어 있음
Thread thread1 = new Thread(new IncrementRunnable(counter));
Thread thread2 = new Thread(new IncrementRunnable(counter));
Thread thread3 = new Thread(new IncrementRunnable(counter));
// thread가 동시 진행되면서 thread들이 겹쳐서 3000까지 제대로 출력하지 못함
// increment()에 synchronized를 사용하면 해결할 수 있음
thread1.start();
thread2.start();
thread3.start();
}
}
- 서버에서 여러 클라이언트 요청 처리
- 여러 클라이언트의 요청을 멀티 쓰레딩을 이용해서 동시 처리
- 깃허브 : https://github.com/kung036/java_task/tree/test/src/practice/day20240516/thread/server
public class ServerAdvanced {
public static void main(String[] args) {
List<Student> studentList = new ArrayList<>(); // 고객 대기 리스트
try (ServerSocket serverSocket = new ServerSocket(5000); // 서버 소켓 생성
) {
System.out.println("Thread : " + Thread.currentThread().getName() + " is running");
System.out.println("서버가 시작되었습니다.");
while (true) {
try {
Socket clientSocket = serverSocket.accept(); // 클라이언트 접속 대기
Thread request = new Thread(new RequestHandler(clientSocket, studentList));
request.start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
'슈퍼코딩 > 주특기(JAVA)' 카테고리의 다른 글
슈퍼코딩 신입연수원 7주차 후기 (0) | 2024.05.18 |
---|---|
2024.05.17(금) 슈퍼코딩 신입연수원 7주차 Day 5 후기 - 디자인 패턴 (0) | 2024.05.17 |
2024.05.15(수) 슈퍼코딩 신입연수원 7주차 Day 3 후기 - I/O Stream, client-server, 직렬화/역직렬화 (0) | 2024.05.15 |
2024.05.14(화) 슈퍼코딩 신입연수원 7주차 Day 2 후기 - 유틸리티 클래스, 내부 클래스, 람다식, stream (0) | 2024.05.14 |
2024.05.13(월) 슈퍼코딩 신입연수원 7주차 Day 1 후기 - Enum, Optional, DataTime (0) | 2024.05.13 |