01. 프로그램
1. 보조기억장치 (하드디스크): 프로그램과 데이터, 영구 저장
2. 주기억장치
(1) 단일 프로그램: 프로그램이 1개, 속도가 느림
(2) 다중프로그램: 메모리에 여러 개의 프로그램이 존재
3. 중앙처리장치
(1) 제어장치: 흐름 제어, 신호등 역할
(2) 연산장치: 값을 구함
4. 프로그램 (Program): 보조기억장치 또는 주기억장치 <저장장치>에 기록 (실행 x)
5. 프로세스 (Process): 주기억장치의 프로그램이 실행되기 위해 CPU로 들어가 실행되는 프로그램
6. 스레드 (Thread): 프로세스를 세분화 시킨 단위, 시분할 사용(TSS, Time Sharing System)
* 자바에서 스레드가 기본 처리의 단위, 입력과 출력은 프로그램 단위
* 스레드를 이용해 병렬 처리가 가능
- 병렬 처리(Parallel Processing): 동시에 처리
- 동시에 처리하려면 CPU가 여러개 필요 -> 하지만 실제로 CPU가 여러개인 경우는 거의 없음
- CPU 하나로 병렬처리 하려면? 시분할 사용
02. 동기화 메소드 및 동기화 블록
1. 임계영역(Critical Section): CPU에서 실행할 때 하나의 스레드만 실행할 수 있는 코드 영역
즉, 하나의 스레드가 실행 중이면 다른 스레드는 들어올 수 없도록 영역을 구분
2. 동기화(Synchronized): 임계 영역에 스레드가 이미 있음을 알려줌 > 다른 스레드가 들어올 수 없도록
03. 스레드를 만드는 방법
* run() 메소드를 오버라이딩(재정의) 필수 + 재정의된 run() 메소드를 실행하려면 start() 메소드를 호출
(1) Thread 클래스를 상속
- java.lang 패키지 > Thread 클래스 > run() 메소드
package com.thread;
public class Korea extends Thread{
@Override
public void run() {
for(int i=0; i<10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("홍길동");
}
}
}
① 3행: Thread 상속
② 9행: Thread.sleep(millisecond): 1초마다 쉬기
③ 6행: 스레드에 있는 모든 메소드는 public
④ 6행: run() 메소드를 오버라이딩(재정의)
package com.thread;
public class KoreaTest {
public static void main(String[] args) {
Korea kor = new Korea();
kor.start();
}
}
[결과화면]
(2) Runnable 인터페이스를 상속
- java.lang 패키지 > Runnable 인터페이스 > run() 메소드(만 존재)
package com.thread;
public class KoreaInterface implements Runnable{
@Override
public void run() {
for(int i=0; i<10; i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("홍길동2");
}
}
}
① 3행: Runnable 인터페이스 상속
package com.thread;
public class KoreaTest {
public static void main(String[] args) {
KoreaInterface korin = new KoreaInterface();
Thread thread = new Thread(korin);
thread.start();
}
}
② 5행: 실행시키기 위해 Thread 객체를 하나 더 생성 후 start() 메소드 사용
[결과화면]
ex) 익명클래스를 이용하면 상속을 받지 않고 Runnable 사용 가능
package com.thread;
public class AnonyTest {
public static void main(String[] args) {
Runnable rr = new Runnable() {
@Override
public void run() {
for(int i=0; i<10; i++) {
System.out.println("홍길동3");
}
}
};
Thread tt = new Thread(rr);
tt.start();
}
}
① 8행: public void run() {}; // 익명 클래스
② 14행: Runnable을 사용했기 때문에 Thread 객체 생성
[결과화면]
ex) 익명 객체 이용 (익명 클래스, 익명 객체 모두 1회성)
package com.thread;
public class AnonyTest2 {
public static void main(String[] args) {
Thread thread = new Thread(()-> {
for(int i=0; i<10; i++) {
System.out.println("홍길동4");
}
}); // 익명객체 이용
thread.start();
}
}
① 5행: Thread thread = new Thread((0 -> {};) // 익명 객체 생성
[결과화면]
위에 4가지 방법이 스레드를 사용한 것인데 원래 쓰던 방식과 별 차이가 없어 보임 -> 아래 예제로 확인
04. 구구단 예제
1. 구구단 (Thread 사용 전)
package com.thread;
public class Multiplication extends Thread {
int input;
public Multiplication(int input) {
super();
this.input = input;
}
void print(){
for(int i=1; i<=9; i++){
System.out.println(this.input + " * " + i + " * " + (this.input*i));
}
}
package com.thread;
import java.util.Scanner;
public class InputTest {
public static void main(String[] args) {
System.out.print("구구단 몇단? ");
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
Multiplication result = new Multiplication(a);
result.print();
}
}
[결과화면]
2. 구구단 (Thread 사용, Thread 상속)
package com.thread;
public class Multiplication extends Thread {
int input;
public Multiplication(int input) {
super();
this.input = input;
}
public void run() {
for(int i=1; i<=9; i++) {
System.out.println(this.input + " * " + i + " = " + (this.input*i));
}
}
}
① 3행: Thread 상속
② 11행: run() 메소드 오버라이딩 (재정의)
package com.thread;
import java.util.Scanner;
public class InputTest {
public static void main(String[] args) {
Multiplication result2 = new Multiplication(2);
Multiplication result3 = new Multiplication(3);
result2.start();
result3.start();
}
}
[결과화면]
* 프로그램 작성 순서는 2단과 3단이지만 순서대로 뜨지 않고 번갈아 가면서 뜨는 것이 확인 가능 -> 시분할 방법
3. 스레드 우선순위 설정 setPriority(Thread.MAX_PRIORITY)
package com.thread;
import java.util.Scanner;
public class InputTest {
public static void main(String[] args) {
Multiplication result2 = new Multiplication(2);
Multiplication result3 = new Multiplication(3);
Multiplication result4 = new Multiplication(4);
result4.setPriority(Thread.MAX_PRIORITY);
result2.start();
result3.start();
result4.start();
}
}
① 10행: Thread.MAX_PRIORITY = 10; // 값이 높을수록 우선순위가 높아짐
[결과화면]
* 하지만 우선순위를 가장 높게 줘도 무조건 맨 처음에 뜨는 것이 아니라 확률이 높아질 뿐
4. 구구단 (Thread 사용, Runnable 상속)
package com.thread;
public class MultipleInterface implements Runnable{
int input;
public MultipleInterface(int input) {
this.input = input;
}
@Override
public void run() {
for(int i=1; i<=9; i++) {
System.out.println(this.input + " * " + i + " = " + (this.input*i));
}
}
public static void main(String[] args) {
MultipleInterface m2 = new MultipleInterface(2);
Thread t2 = new Thread(m2);
t2.start();
Thread t3 = new Thread(new MultipleInterface(3));
t3.start();
}
}
[결과화면]
* Thread 상속과 방식의 차이 -> 둘 다 시분할
05. 스레드 상태 제어
(1) UpDown.java
package com.thread;
public class UpDown {
int data;
public UpDown(int data) {
super();
this.data = data;
}
public synchronized void up() {
data++;
System.out.println("증가 " + data);
}
public synchronized void down() {
data--;
System.out.println("감소 " + data);
}
}
(2) UpThread.java
package com.thread;
public class UpThread extends Thread{
UpDown data; // UpDown클래스에서 공통으로 사용할 data를 호출해 사용
public UpThread(UpDown data) {
super();
this.data = data;
}
public void run() {
for(int i=0; i<5; i++)
data.up();
}
}
① 4행: UpDown 클래스에서 data를 호출
② 6행: UpThread 생성자
③ 11행: run() 메소드 오버라이딩
(3) DownThread.java
package com.thread;
public class DownThread extends Thread{
UpDown data;
public DownThread(UpDown data) {
super();
this.data = data;
}
public void run() {
for(int i=0; i<5; i++)
data.down();
}
}
① 4행: UpDown 클래스에서 data를 호출
② 6행: DownThread 생성자
③ 11행: run() 메소드 오버라이딩
(4) UpDownTest.java (main)
package com.thread;
public class UpDownTest {
public static void main(String[] args) {
UpDown updown = new UpDown(0);
UpThread up = new UpThread(updown);
DownThread down = new DownThread(updown);
up.start();
down.start();
}
}
① 7행: UpThread의 생성자로 들어가 this.data = data; 실행
② 8행: DownThread의 생성자로 들어가 this.data = data; 실행
[결과화면]
* 증가, 감소가 순차적이지 않고 시분할 (Thread)
0. Synchronized: 동기화 > 임계 영역을 잡아 주는 것
1. notifyAll(): wait()에 의해 중지된 메소드를 실행 모드로 변경
2. wait(): 실행 중인 메소드를 중지 (<->notify)
(1) UpDown 클래스만 수정
package com.thread;
public class UpDown {
int data;
public UpDown(int data) {
super();
this.data = data;
}
public synchronized void up() {
if(data>=3) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println("증가 " + data);
notifyAll();
}
public synchronized void down() {
if(data<=0)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
data--;
System.out.println("감소 " + data);
notifyAll();
}
}
① 14행: wait(): 값이 3이상이면 스레드 중지 (4가 넘을 수 없음)
② 21행: notifyAll(): down()메소드를 실행하라
③ 27행: wait(): 값이 0이하이면 스레드 중지 (음수가 될 수 없음)
④ 33행: notifyAll(): up()메소드를 실행하라
[결과화면]
* (0~3)사이의 값만 나옴
(3) join(): 실행 중지 시켰다가 나중에 실행
package com.thread;
public class Multiplication extends Thread {
int input;
public Multiplication(int input) {
super();
this.input = input;
}
public void run() {
if(this.input == 5)
try {
join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=1; i<=9; i++) {
System.out.println(this.input + " * " + i + " = " + (this.input*i));
}
}
}
package com.thread;
public class InputTest {
public static void main(String[] args) {
Multiplication result5 = new Multiplication(5);
result5.start();
}
}
[결과화면]
* 5초 후에 5단 구구단이 출력됨
'STUDY > Java' 카테고리의 다른 글
[JAVA] Collection (List, Set, Map) (0) | 2021.11.05 |
---|---|
[JAVA] Generic 제네릭 (0) | 2021.11.05 |
[JAVA] 예외처리 (0) | 2021.11.05 |
[JAVA] 정렬, 익명클래스 (0) | 2021.11.05 |
[JAVA] 데이터 타입 - 기본타입, 참조타입 (0) | 2021.11.05 |