1. 과제
- 빨간 동그라미를 '말'이라 하고 시작 버튼을 누름과 동시에 각자 달립니다.
- 도착하는 순서대로 등수를 표현해주세요.
2. 필요 개념
* Thread
1) 정의
: 스레드는 프로세스 내에서 실행되는 여러 실행 흐름 중 하나로, 가장 작은 실행 단위입니다.
그동안 했던 과제는 main 스레드 하나로 실행해왔던 겁니다..!
2) 스레드의 장점
- 멀티태스킹 : 한 프로세스 내에서 여러 작업을 동시에 수행할 수 있습니다.
- 자원 공유 : 같은 프로세스 내의 스레드끼리 메모리(데이터, 힙)을 공유합니다.
- 응답성 향상 : 하나의 스레드가 작업을 수행하는 동안 다른 스레드는 다른 작업을 계속 할 수 있어 프로그램 반응시간이 단축됩니다.
3) 스레드 다룰 때 주의점
- 동시성 문제 : 여러 스레드가 같은 자원을 동시에 수정하려 할 때 문제가 발생할 수 있습니다.
- 데이터 무결성 : 스레드 간의 적절한 동기화 없이 데이터를 공유하면 원하지 않는 결과가 나올 수 있습니다.
(syncronized블록을 사용해서 해결할 수 있습니다.)
4) 생성 및 실행 방법
1️⃣ Thread 클래스를 상속받아 run 메서드를 오버라이드합니다.
public class SimpleThread extends Thread {
@Override
public void run() {
// 스레드가 실행할 작업을 여기에 작성합니다.
System.out.println("스레드가 실행 중입니다.");
}
public static void main(String[] args) {
// SimpleThread 인스턴스를 생성합니다.
SimpleThread thread = new SimpleThread();
// 스레드를 시작합니다.
thread.start();
// 메인 스레드의 다른 작업을 계속할 수 있습니다.
System.out.println("메인 스레드는 다른 작업을 진행 중입니다.");
}
}
2️⃣ Runnable 인터페이스를 구현하여 run 메서드를 정의하고 이를 Thread 객체에 전달합니다.
public class SimpleRunnable implements Runnable {
@Override
public void run() {
// 스레드가 실행할 작업을 여기에 작성합니다.
System.out.println("스레드가 실행 중입니다.");
}
}
public class SimpleThreadExample {
public static void main(String[] args) {
// Runnable 객체를 생성합니다.
Runnable task = new SimpleRunnable();
// 스레드를 생성하고 Runnable 객체를 전달합니다.
Thread thread = new Thread(task);
// 스레드를 시작합니다.
thread.start();
// 메인 스레드의 다른 작업을 계속할 수 있습니다.
System.out.println("메인 스레드는 다른 작업을 진행 중입니다.");
}
}
3. 해결 과정
- GUI 그래픽 코드는 과제 문제에 미리 구현해주셔서 개꿀이었습니다..?
- MyFrame 클래스에서 그래픽을 보여주고 스레드를 생성하고 실행하는 역할을 합니다.
- Horse클래스는 말의 좌표값, 각자 말들을 그리는 메서드, 스레드 실행 메서드(run)을 정의합니다.
대략적인 구조를 도식화해봤습니다.
MyFrame
Horse
해결하던 도중, 등수 표시하는 데에 에러가 났습니다.
첫번째로, List<Horse> passedHorse = new ArrayList<>(); 로 동적배열을 만들고
통과할때마다 통과한 말을 배열에 담아줬습니다.
그리고 말이 결승선에 도달했을 때마다, 리스트 배열의 this의 인덱스에 +1을 해서 등수 표시가 되도록 했습니다.
=> 이 코드로 실행을 하면 등수표시가 안되고 디버깅을 하면 등수표시가 되는 요상한 문제가 있었습니다.
두번째로, 정적 변수로 rank=1;로 초기화해주고 rank함수가 실행될때마다 rank를 1씩 증가시켜줬습니다.
이걸로 해결됐습니다.
4. 결과
MyFrame
package Day11_HorseGame;
import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MyFrame extends Frame{
public static final int FRAME_WIDTH=800;
public static final int FRAME_HEIGTH=600;
private Button btn1 = new Button();
private Button btn2 = new Button();
public static final int HORSE_ARR_SIZE=5;
private Horse[] arr =new Horse[HORSE_ARR_SIZE];
private boolean start;
public MyFrame() {
makeHorse();
makeMainUi(); //화면구성
setSize(FRAME_WIDTH, FRAME_HEIGTH);
setVisible(true);
}
public void makeHorse() {
for(int i=0; i<arr.length; i++){
arr[i]=new Horse();
}
}
private void makeMainUi(){
//고급 그래픽
Panel pNorth = new Panel();
Panel pCenter = new Panel();
btn1.setLabel("시작");
btn1.addActionListener(new MyBtnHandler());
btn2.setLabel("종료");
btn2.addActionListener(new MyBtnHandler());
pNorth.add(btn1);
pNorth.add(btn2);
pCenter.setLayout(new GridLayout(HORSE_ARR_SIZE,1));
for(Horse h:arr){
pCenter.add(h);
}
this.add("North",pNorth);
this.add("Center", pCenter);
}
class MyBtnHandler implements ActionListener {
Thread t[] = new Thread[HORSE_ARR_SIZE];
@Override
public void actionPerformed(ActionEvent e) {
// Thread(Horse) 생성 및 실행
if(e.getSource() == btn1){
for(int i = 0; i < HORSE_ARR_SIZE; i++) {
t[i] = new Thread(arr[i]); //스레드 생성
}
for(int i = 0; i < HORSE_ARR_SIZE; i++) {
t[i].start(); //스레드 실행
}
} else if(e.getSource() ==btn2){
System.exit(0); //종료
}
}
}
};
Horse
package Day11_HorseGame;
import java.awt.*;
import java.util.*;
import java.util.List;
public class Horse extends Canvas implements Runnable{
public static final int HORSE_SIZE = 50;
public static final int RUN_DISTANCE = 700;
private int x;
private int y;
private static int rank = 1;
public Horse(){
this.x = 20;
this.y = 20;
}
public void paint(Graphics g){
g.setColor(Color.RED);
g.fillOval(x,y,HORSE_SIZE,HORSE_SIZE);
if(x > RUN_DISTANCE ) {
rank(g);
}
}
public void rank(Graphics g){
g.setColor(Color.BLACK);
g.drawString((rank++)+"등",x-20,y-1);
}
@Override
public void run() {
Random rnd = new Random();
while (x <= RUN_DISTANCE){
this.x += rnd.nextInt(5); //오른쪽으로 좌표이동.
repaint();
try {
Thread.sleep(10);//스레드 실행을 일시정지
} catch (InterruptedException e) {
System.out.println("깨어났습니다.");
}
}
}
}
'프로그래밍 언어 > Java' 카테고리의 다른 글
[JSP] 게시판 만들기 | 1편. 환경 설정 및 JSP 개념 이해 (0) | 2024.02.07 |
---|---|
[Java]Socket을 활용한 간단한 클라이언트-서버 통신 (1) | 2023.12.28 |
[Java] 제네릭(generic)의 개념과 활용법 (1) | 2023.12.19 |
[과제] UML에 맞게 싱글톤 패턴 적용하기 (0) | 2023.12.18 |
[Java] 싱글톤 패턴 개념 및 구현방법 (0) | 2023.12.18 |