1. 예제 1 (단일 스레드)
package ex16;
class MyFile {
//하드디스크 기록 (I/O)
public void write() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("파일 쓰기 완료");
}
}
class 화가 {
public void 그림그리기() {
System.out.println("그림 그리기 완료");
}
}
public class ThreadEx02 {
public static void main(String[] args) {
화가 h = new 화가();
h.그림그리기();
MyFile mf = new MyFile();
mf.write();
}
}
단일 스레드에서는 스레드 간의 경합이 없으므로
Thread.sleep(2000)와 같은 메서드를 사용할 필요가 없다.
2. 예제2 (멀티 스레드)
package ex16;
class MyFile {
//하드디스크 기록 (I/O)
public void write() { //서브 스레드에서 run하는 메소드
try {
Thread.sleep(5000); //멀티 스레드에는 애가 무조건 있어야
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("파일 쓰기 완료");
}
}
class 화가 {
public void 그림그리기() { //메인 스레드에서 run하는 메소드
System.out.println("그림 그리기 완료");
}
}
public class ThreadEx02 {
public static void main(String[] args) {
new Thread(() -> { //여기서부터 스레드 줄기 나뉘기 시작~!
MyFile mf = new MyFile(); >>새로운 스레드의 메인 메서드 (서브스레드 줄) //Thread t1 = new Thread(new MyRunnable("A")) 이런식으로 사용했으니까, 클래스를 new한게 아닐지?
mf.write(); >>새로운 스레드의 메인 메서드
}).start(); >> 이 부분은 새로운 스레드가 운영함 (서브스레드)
화가 h = new 화가(); >> 메인스레드!!가 쳐줌!~!
h.그림그리기();
}
}


메인 스레드 먼저 작동 후, 서브 스레드가 나왔다. 일을 동시에 실행할 수 있게 됨!

new Thread() 생성자를 사용하여 스레드를 생성할 때
Runnable 객체를 매개변수로 전달하여 해당 스레드가 실행할 작업을 지정할 수 있다.


내부에서 MyFile 객체를 생성하는 이유는
호출할 메소드인 write()가 MyFile 객체 안에 있어서 그런거야

[MyFile 클래스의 write() 메소드는 I/O 작업을 수행]

3. 예제3 (데몬 스레드)
3-1. 코드1
package ex16.example3;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ThreadEx03 extends JFrame {
private int count = 0;
private JLabel countLabel;
public ThreadEx03() {
setTitle("숫자 카운터 프로그램");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 레이아웃 매니저 설정
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
// 숫자를 표시할 레이블 생성
countLabel = new JLabel("현재 숫자: " + count);
countLabel.setAlignmentX(CENTER_ALIGNMENT);
add(countLabel);
// 증가 버튼 생성
JButton increaseButton = new JButton("멈춤");
increaseButton.setAlignmentX(CENTER_ALIGNMENT);
add(increaseButton);
// 버튼에 액션 리스너 추가
increaseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
setVisible(true);
while (true) {
try {
Thread.sleep(1000);
count++;
countLabel.setText("현재 숫자: " + count);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
public static void main(String[] args) {
new ThreadEx03();
}
}

아직 버튼을 눌러도 멈추진 않는다.
3-2. 데몬 스레드

처음 while문이 데몬 스레드라서 '도달할 수 없다고 뜬다.'
처음 while문이 끝나야지 2번째 while문으로 넘어가는데 영원히 도니까... ㅠㅠ
넘어갈 수가 없음!!

이건 멀티 스레드. 두 개가 갈라져서 둘이서 같이 영원히 돈다.
이렇게 while이 있는 스레드는 영원히 죽지않는 스레드라고해서 '데몬 스레드' 라고 불림
코드
package ex16.example3;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ThreadEx03 extends JFrame {
private int count = 0;
private int count2 = 0;
private JLabel countLabel;
private JLabel count2Label;
public ThreadEx03() {
setTitle("숫자 카운터 프로그램");
setSize(300, 200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 레이아웃 매니저 설정
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
// 숫자를 표시할 레이블 생성
countLabel = new JLabel("숫자1: " + count);
count2Label = new JLabel("숫자2: " + count2);
countLabel.setAlignmentX(CENTER_ALIGNMENT);
count2Label.setAlignmentX(CENTER_ALIGNMENT);
add(countLabel);
add(count2Label);
// 증가 버튼 생성
JButton increaseButton = new JButton("멈춤");
increaseButton.setAlignmentX(CENTER_ALIGNMENT);
add(increaseButton);
// 버튼에 액션 리스너 추가 //람다식 쓰기
increaseButton.addActionListener(e -> {
System.out.println("버튼 클릭됨");
});
//타겟(run 메소드) 넣어주기
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
count++;
countLabel.setText("숫자1: " + count);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}).start();
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
count2++;
count2Label.setText("숫자2: " + count2);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}).start();
}
public static void main(String[] args) {
new ThreadEx03();
}
}

3-3. 스레드를 멈추는 법 ★
ture, false를 걸어서 멈춤
스레드는 상태값으로 멈춘다!!


멈추는 코드
package ex16.example3;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ThreadEx03 extends JFrame {
private boolean state = true; //스레드를 제어하는 상태변수 (힙에 있음)
private int count = 0;
private int count2 = 0;
private JLabel countLabel;
private JLabel count2Label;
public ThreadEx03() {
setTitle("숫자 카운터 프로그램");
setSize(300, 200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 레이아웃 매니저 설정
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
// 숫자를 표시할 레이블 생성
countLabel = new JLabel("숫자1: " + count);
count2Label = new JLabel("숫자2: " + count2);
countLabel.setAlignmentX(CENTER_ALIGNMENT);
count2Label.setAlignmentX(CENTER_ALIGNMENT);
add(countLabel);
add(count2Label);
// 증가 버튼 생성
JButton increaseButton = new JButton("멈춤");
increaseButton.setAlignmentX(CENTER_ALIGNMENT);
add(increaseButton);
// 버튼에 액션 리스너 추가 //람다식 쓰기
increaseButton.addActionListener(e -> {
state = false;
});
//타겟(run 메소드) 넣어주기
new Thread(() -> {
while (state) {
try {
Thread.sleep(1000);
count++;
countLabel.setText("숫자1: " + count);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}).start();
new Thread(() -> {
while (state) {
try {
Thread.sleep(1000);
count2++;
count2Label.setText("숫자2: " + count2);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}).start();
}
public static void main(String[] args) {
new ThreadEx03();
}
}
살짝 느리게 멈추는 이유
: sleep 때문에. 잠깐 sleep했을 때 멈추려고 끼어들기 때문
Share article