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