프로세스와 스레드
프로세스
- 하나의 프로그램이 실행될 때 운영체제로부터 실행에 필요한 자원을 독립적으로 할당받고 애플리케이션 실행에 필요한 환경을 제공한다.
- 실행중인 프로그램 하나당 프로세스가 하나씩 생긴다.
- 멀티태스킹(Multi tasking)
- 동시에 두개 이상의 프로세스(프로그램)의 실행을 지원하는 것
- 프로세스마다 실행에 필요한 자원(CPU, 메모리)들을 적절히 할당하고, 관리하는 기술이 필요하다
스레드
- 프로세스가 수행문을 실행하기 위해서 사용하는 실행흐름(일꾼)이다.
- 모든 프로세스는 하나 이상의 스레드를 가지고 있다.
프로그램을 스레드를 기준으로 구분
- 싱글 스레드 프로그램 : 실행흐름이 하나뿐인 프로그램
- 멀티 스레드 프로그램 : 실행흐름이 두개 이상인 프로그램
메인 스레드 : 모든 자바 프로그램은 main( ) 메소드의 수행문을 실행시키는 메인 스레드(Main Thread)를 가지고 있다
사용자정의 스레드 만들기
java.lang.Thread 클래스를 상속받아서 만들기
public class MyThread extends Thread {
public void run() {
// 스레드로 수행시킬 작업
}
}
// 스레드 생성 및 실행
MyThread t = new MyThread();
t.start();
Thread 클래스로 작성한 스레드 예시코드
java.lang.Runnable 인터페이스를 구현받아서 만들기
public class MyRunnable implements Runnable {
public void run() {
// 스레드로 수행시킬 작업
}
}
// 스레드 생성 및 실행
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
Runnable 인터페이스로 구현한 스레드 예시코드
synchronize
동기화처리
- 멀티스레드 환경에서 실행되는 프로그램이 임계값(여러 스레드가 동시에 변경할 수 있는 값)을 가지고 있다면, 해당 프로그램은 Thread - Unsafe한 프로그램이 된다
- 멀티스레드의 동시접근을 차단하는 것이 동기화처리
동기화 블록 정의하기
- 동기화처리된 메소드를 만든다
- 메소드내의 모든 수행문이 동기화처리의 대상이 된다
public class Sample {
필드타입 필드명; //임계값
public synchronized void work() {
임계값을 변경하는 수행문;
임계값을 변경하는 수행문;
임계값을 변경하는 수행문;
임계값을 변경하는 수행문;
임계값을 변경하는 수행문;
}
}
- 동기화 블록을 정의한다
public class Sample {
필드타입 필드명; // 임계값
public void work() {
그냥 수행문;
그냥 수행문;
synchronized(this) {
임계값을 변경하는 수행문;
임계값을 변경하는 수행문;
}
그냥 수행문;
}
}
콜렉션의 동기화처리
- 동기화 처리가 지원되는 클래스를 사용
- Vector (ArrayList 대신)
- HashTable (HashMap 대신)
- 동기화처리가 지원되지 않는 클래스를 동기화처리가 가능하게 하기
- List list = Collections.synchronizedList(new ArrayList());
- Set set = Collections. synchronizedSet(new HashSet());
- Map<String, Object> map = Collections. synchronizedMap(new HashMap<String, Object>());
멀티스레드 환경에서 안전한 클래스 작성하기
- 여러 스레드가 동시에 변경할 수 있는 필드를 정의하지 않는다
- 필드를 읽기전용의 용도로 사용한다
- 업무로직 수행에 필요한 값들은 해당 메소드내의 변수에만 저장한다
스레드 예시 코드
package thread3;
import java.util.Vector;
import javax.xml.stream.events.Namespace;
public class HorseRunnable implements Runnable {
// 순위별로 경주마의 이름을 저장하는 객체
private Vector<String> names = new Vector<String>();
public Vector<String> getnames() {
return names;
}
@Override
public void run() {
// TODO Auto-generated method stub
String name = Thread.currentThread().getName();
for(int i =1; i<=100; i++) {
System.out.println("["+ name + "]이" + i + "미터 전진함");
try {
Thread.sleep((int) (Math.random()*2000));
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.println("["+ name + "이 결승선에 도착함");
names.add(name);
}
}
위 코드를 실행하는 코드
package thread3;
import java.util.Vector;
public class App2 {
public static void main(String[] args) throws Exception {
HorseRunnable runnable = new HorseRunnable();
Thread t1 = new Thread(runnable, "번개");
Thread t2 = new Thread(runnable, "천둥");
Thread t3 = new Thread(runnable, "백호");
Thread t4 = new Thread(runnable, "한라");
Thread t5 = new Thread(runnable, "금강");
System.out.println("경주를 시작합니다");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
/*
* join()
* - 이 메소드를 호출한 스레드가 종료될 때가지 기다려따고 남은 수행문을 실행
*/
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
// 이 수행문을 모든 스레드의 실행이 종료될 때까지 기다렸다가 실행한다
System.out.println("경주를 종료합니다");
Vector<String> names = runnable.getnames();
System.out.println("경기결과");
System.out.println("1등: " + names.get(0));
System.out.println("2등: " + names.get(1));
System.out.println("3등: " + names.get(2));
System.out.println("4등: " + names.get(3));
System.out.println("5등: " + names.get(4));
}
}
'Java' 카테고리의 다른 글
Java_익명 내부 클래스, 람다식 (0) | 2024.02.26 |
---|---|
Java_네트워크, I/O (0) | 2023.11.29 |
Java_I/O(입출력) (1) | 2023.11.27 |
Java_객체의 직렬화와 역직렬화 (1) | 2023.11.26 |
Java_예외처리 (0) | 2023.11.22 |