[ Thread ]
- Thread : 하나의 프로그램에서 실행되는 흐름의 단위
- Multi thread : 동시에 스레드를 진행할 수 있는 것 (ex. 카톡 : 채팅하다가 파일을 전송 가능)
> 자바는 멀티태스크, 멀티 스레드 환경을 지원
* Multi Thread 구현 방법
1. Thread 클래스 상속
2. Runnable 인터페이스 구현 : run() override
3. start() 실행
- Thread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package day18;
// CPU, RAM
// 컴퓨터가 느린 것 같아
// 1. CPU : 2개 이상
// 2. RAM : 작업공간
// 3. 그래픽카드 : 가상화폐, 채굴..
// 메모리를 할당 받아 실행중인 프로그램 ==> 프로세스
// 멀티 태스크
// Word 프로세스, 음악..
// 하나의 프로그램에서 실행되는 흐름의 단위 : Thread
// 동시에 : Multi thread
// 카톡 : 채팅하다가 파일을 전송 가능
// 자바는 멀티태스크, 멀티 쓰레드 환경을 지원
// Multi Thread 구현 방법
// 1. Thread 상속
// 2. Runnable 인터페이스 구현
public class ThreadEx1 {
private void name() {
Thread th = Thread.currentThread(); // 현재 실행 중인 쓰레드 객체를 리턴
String name = th.getName(); // 현재 실행 중인 쓰레드의 이름을 리턴
System.out.println("현재 실행 중인 쓰레드의 이름은 : "+name);
}
}
|
cs |
- Multi Thread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package day18;
// 멀티 쓰레드
// 1. Thread 클래스 상속
// 2. run() override
// 3. start() 실행
public class ThreadEx2 extends Thread{ // Thread 상속
ThreadEx2(String name) {
// super();
super(name); // String 매개변수를 갖는 부모 생성자를 호출
}
// 부모가 가지고 있는 method를 다시 정의해서 사용 : override
@Override
public void run() {
for(int i = 1; i<=100; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i + " 미터 달리는 중");
try {
Thread.sleep((int)(Math.random()*100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadEx2 th1 = new ThreadEx2("천둥이");
ThreadEx2 th2 = new ThreadEx2("번개");
// 각 Thread는 독립적
th1.start(); // 준비가 되면 실행해
th2.start();
System.out.println(Thread.currentThread().getName() + " main thread end");
}
}
|
cs |
- 멀티스레드 : Thread 클래스를 상속받지 못하는 경우 (단일상속만 지원)
1. Runnable 인터페이스 구현
2. run() override
3. 이 객체를 생성
4. Thread 객체를 생성(생성자로 이 객체) : Thread(Runnable target)
5. Thread 클래스 객체를 통해서 start() 호출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package day18;
// 멀티쓰레드 : Thread 클래스를 상속받지 못하는 경우 : (단일상속만 지원)
// 1. Runnable 인터페이스 구현
// 2. run() override
// 3. 이 객체를 생성
// 4. Thread 객체를 생성(생성자로 이 객체) : Thread(Runnable target)
// 5. Thread 클래스 객체를 통해서 start() 호출
// 1.
public class ThreadEx3 implements Runnable {
String name; // 스레드 이름으로 쓰기 위해 선언
ThreadEx3(String name) {
this.name = name;
}
// 2.
@Override
public void run() { // run 메서드 오버라이드
for(int i=1; i<=100; i++) {
System.out.println(name + " : " + i + "미터 달리는 중");
}
}
public static void main(String[] args) { // 메인에서 객체 생성
// 3.
ThreadEx3 r1 = new ThreadEx3("토끼");
ThreadEx3 r2 = new ThreadEx3("거북이");
// 4.
Thread th1 = new Thread(r1); // 스레드 객체 생성해서 runnable을 매개변수로
Thread th2 = new Thread(r2);
// 5.
th1.start(); // 메인 스레드 실행되고, 준비되면 얘도 실행시킴
th2.start();
}
}
|
cs |
* 경주 게임 (활용)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
package day18;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Racing extends JFrame implements ActionListener{
JButton jbtn1, jbtn2, jbtn3, jbtnStart;
ImageIcon img1, img2;
Horse h1, h2, h3;
Racing() {
setLayout(null);
img1 = new ImageIcon("src/images/Horse.gif");
img2 = new ImageIcon("src/images/Horsestop.gif");
jbtn1 = new JButton(img2);
jbtn2 = new JButton(img2);
jbtn3 = new JButton(img2);
jbtnStart = new JButton("Start");
jbtn1.setBounds(50, 150, 120, 60);
jbtn2.setBounds(50, 250, 120, 60);
jbtn3.setBounds(50, 350, 120, 60);
jbtnStart.setBounds(200, 650, 800, 50);
add(jbtn1);
add(jbtn2);
add(jbtn3);
add(jbtnStart);
jbtnStart.addActionListener(this);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(100, 100, 1200, 800);
setVisible(true);
}
public static void main(String[] args) {
Racing r = new Racing();
}
@Override
public void actionPerformed(ActionEvent e) {
// System.out.println("레이싱 클래스에서 jbtn1 : "+jbtn1);
if( h1 == null) {
h1 = new Horse(jbtn1, img1, img2);
h2 = new Horse(jbtn2, img1, img2);
h3 = new Horse(jbtn3, img1, img2);
h1.start();
h2.start();
h3.start();
}
// // 1. 버튼의 현재 위치를 가져오기
// int x = jbtn1.getX();
// int y = jbtn2.getY();
//
// // 2. 버튼의 x 값을 약간 증가
// x += 3;
// // 3. 지정된 위치로 버튼을 이동
// jbtn1.setLocation(x,y);
//
// for(int i=0; i<100; i++) {
// jbtn1.setLocation(jbtn1.getX()+3, jbtn1.getY());
// jbtn2.setLocation(jbtn1.getX()+3, jbtn2.getY());
// jbtn3.setLocation(jbtn1.getX()+3, jbtn3.getY());}
//
// try {
// Thread.sleep(5);
// } catch (InterruptedException e1) {
// e1.printStackTrace();
// }
}
}
|
cs |
- Multi Thread 활용 > 말 세 마리를 동시에 달릴 수 있도록
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package day18;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
// 멀티 쓰레드
public class Horse extends Thread{
JButton jbtn; // Racing의 jbtn 버튼 참조 가능
ImageIcon img1;
ImageIcon img2;
Horse(JButton jbtn) {
this.jbtn = jbtn;
// System.out.println("Horse 클래스 생성자 : "+this.jbtn1);
}
Horse(JButton jbtn, ImageIcon img1, ImageIcon img2) {
this.jbtn = jbtn;
this.img1 = img1;
this.img2 = img2;
}
@Override
public void run() {
// 달리는 말 이미지로 교체
jbtn.setIcon(img1);
// 동시에 처리할 코드
Random rnd = new Random();
for(int i=0; i<100; i++) {
jbtn.setLocation(jbtn.getX()+rnd.nextInt(20), jbtn.getY());
try {
Thread.sleep(50);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
// 정지해 있는 말 이미지로 교체
jbtn.setIcon(img2);
}
}
|
cs |
* ATM
- 다양한 매개변수 있는 생성자 사용 (source - generate constructor using fields)
> getter, setter, constructor
- synchronized : 동기화 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package day18;
public class ATM {
String account;
int balance;
ATM(){ // 기본 생성자
}
// 매개변수 있는 생성자 : source - generate constructor using fields
public ATM(String account, int balance) {
super();
this.account = account;
this.balance = balance;
}
// 다양한 매개변수가 있는 생성자 사용 : getter, setter, constructor
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
// synchronized : 동기화 처리
public synchronized void deposit(int money) {
balance += money;
System.out.println(money + "원 입금합니다.");
System.out.println("현재 잔액 : " + balance);
}
// synchronized : 동기화 처리
public synchronized void withDraw(int money) {
if (balance >= money) { // 마이너스 통장 안되게
balance -= money;
System.out.println(money + "원 출금합니다.");
} else {
System.out.println("잔액이 부족합니다.");
}
System.out.println("현재 잔액 : "+balance);
}
}
|
cs |
- ATM Test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package day18;
public class ATMTest {
public static void main(String[] args) {
ATM atm = new ATM("홍길동", 10000);
// 5000 입금
// atm.deposit(5000);
// 20000 출금
// atm.withDraw(20000);
// 12000 출금
// atm.withDraw(12000);
// Multi Thread로 만들어서 동시에 입금, 출금 하도록 > ATMThread
// 동시에 여러 은행 지점에서 이 계좌에
// 입금, 출금을 동시에 처리한다는 가정
ATMThread at1 = new ATMThread(atm);
ATMThread at2 = new ATMThread(atm);
ATMThread at3 = new ATMThread(atm);
// 동기화 처리 > 작업을 한 명씩 하게 하는 것..이 필요
// 동기화 : 데이터 베이스의 lock
// 동기화하면 느려진다..는 단점이 있음 (lock이 걸리기 때문)
at1.start();
at2.start();
at3.start();
}
}
|
cs |
- ATM Multi Thread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package day18;
import java.util.Random;
// 동시에 하나의 계좌에 입금과 출금 기능을
// 수행할 수 있도록 멀티 쓰레드 구현
public class ATMThread extends Thread {
ATM atm;
public ATMThread(ATM atm) {
super();
this.atm = atm;
}
@Override
public void run() {
Random rnd = new Random();
// 5회 입금 번갈아 가면서 5회 출금
boolean flag = true;
for(int i = 0; i<10; i++) {
int money = rnd.nextInt(10)*1000;
if(flag) {
atm.deposit(money);
} else {
atm.withDraw(money);
}
flag = !flag; // 참이면 거짓으로, 거짓이면 참으로 만들고 할당
}
// 랜덤하게 입.출금
}
}
|
cs |
* Car(차고)
- 차고 생성 > ArrayList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package day18;
import java.util.ArrayList;
import java.util.Random;
public class Car {
// 차고
ArrayList<String> list;
String[] carNamelist = {"벤틀리", "그랜져", "벤츠", "폭스바겐", "붕붕카"};
Car() { // 기본생성자 (차고)
list= new ArrayList<String>();
}
// 자동차 이름을 얻어오기 getCarName()
public String getCarName() {
Random rnd = new Random();
// rnd.nextInt(5); 0~4까지 수 리턴
// int pos = rnd.nextInt(5);
// carNameList[pos] : 랜덤한 위치의 포지션을 갖는 배열의 요소
return carNamelist[rnd.nextInt(5)]; // 내가 가진 차 목록 중 한 개를 랜덤하게 추출
}
// 차량을 생성해서 차고에 넣는 메서드 push();
public synchronized void push(String car) {
System.out.println("현재 차고 상태 : "+list);
System.out.println("자동차가 생성되었습니다. : "+car);
list.add(car);
// 자고 있는 고객이 있다면 깨워줌
// this.notify(); // 한 명만 깨움
this.notifyAll();
}
public synchronized String pop() { // 가장 마지막에 있는 차를 꺼내서 출력
String carName = null;
System.out.println("pop() : 현재 차고 상태 "+ list);
//차가 있으면 출고
if(list.size() == 0) {
System.out.println("차고에 차량이 없습니다. 잠시 기다리세요.");
// 없으면 기다려
try {
this.wait(); // 쿨쿨.. 반드시 synchronized 메서드여야 함
} catch (InterruptedException e) {
e.printStackTrace();
}
}
carName = list.remove(list.size() -1);
System.out.println("자동차가 출고 되었습니다."+carName);
return carName;
}
}
|
cs |
- 차량 생산
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package day18;
public class Producter extends Thread { // 쓰레드 상속 -> 멀티쓰레드 하기 위해
private Car car;
public Producter(Car car) {
super();
this.car = car;
}
@Override
public void run() {
// 차량을 20대를 2초마다 1대씩 생산
for(int i=0; i<20; i++) {
// 2초 잠들기 > Thread.sleep(2000)하고, 클릭해서 추가
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 차량 이름을 얻어오기
String name = car.getCarName();
// 차고에 넣기
car.push(name);
}
}
}
|
cs |
- 차량 구매
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package day18;
import java.util.Random;
public class Customer extends Thread{
Car car;
public Customer(Car car) { // 생성자
super();
this.car = car;
}
@Override
public void run() {
// 20대 차량 구매
Random rnd = new Random();
for(int i=0; i<20; i++) {
try { // surround with try/catch
Thread.sleep(rnd.nextInt(5) *1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 1대씩 꺼내기 : 구매
String carName = car.pop();
}
}
}
|
cs |
- 메인 메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package day18;
public class ProductCustomerEx {
public static void main(String[] args) {
Car car = new Car();
// 자동차 생산
Producter p = new Producter(car);
// 자동차 소비
Customer c = new Customer(car);
p.start();
c.start();
}
}
|
cs |
'Java' 카테고리의 다른 글
[Java] I/O Stream (InputStream / OutPutStream) (0) | 2023.03.28 |
---|---|
[Java] 로또 번호 추첨기 - 볼 이미지 부착 (ActionListener, ImageIcon, Random, Multi Thread 등 활용) (0) | 2023.03.28 |
[Java] Exception ( Error, Exception, 예외 처리, 예외 전가) (0) | 2023.03.27 |
[Java] JFrame - Swing (이미지 아이콘, 메모장, 채팅) (0) | 2023.03.24 |
[Java] Generic (미지수 T) + settergetter 설정, 향상된 for문 (0) | 2023.03.24 |