본문 바로가기
코리아 IT아카데미/Java

15일차 | GUI 복습, Thread

by Sharon kim 2021. 11. 9.

본인이 해보기

1. 새이미지, 2. BorderLayout, FlowLayout 으로 패널과 버튼 만들기, 3. 버튼으로 thread 이미지 좌우 멈추고 시작하기

package ch03;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyFrame8_1 extends JFrame{
	
	BorderLayout borderLayout;
	FlowLayout flowLayout;
	JPanel panel;
	JButton button1; 
	JButton button2; 
	BufferedImage backgroundImage;
	BufferedImage imageIcon1;
	MyImagePanel imagePanel;
	int xPoint = 200;
	int yPoint = 200;
	
	public MyFrame8_1() {
		initData();
		setInitLayout();
		addEventListener();
	}
	private void initData() {
		setTitle("이미지 백그라운드 연습");
		setSize(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		borderLayout = new BorderLayout();
		panel = new JPanel();
		button1 = new JButton("start");
		button2 = new JButton("stop");
		
		try {
			backgroundImage = ImageIO.read(new File("sea.png"));
			imageIcon1 = ImageIO.read(new File("fish.png"));
		} catch (Exception e) {
			System.err.println("파일이 없습니다.");
			System.exit(0);
		}
		imagePanel = new MyImagePanel();
	}
	private void setInitLayout() {
		this.setVisible(true);
		this.setResizable(false);
		this.add(imagePanel);
		this.add(panel, BorderLayout.SOUTH);
		panel.setBackground(Color.white);
		panel.setPreferredSize(new Dimension(500,100));
		panel.add(button1);
		panel.add(button2);
		button1.setBackground(new Color(255,255,255));
		button2.setBackground(new Color(255,255,255));
		
	}
	private void addEventListener() {
		this.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				int keyCode = e.getKeyCode();
				switch(keyCode){
				case KeyEvent.VK_UP :
					yPoint = (yPoint <= -40)? 0 : yPoint - 10;
					break;
				case KeyEvent.VK_DOWN :
					yPoint = (yPoint >= 220)? 220 : yPoint + 10;
					break;
				case KeyEvent.VK_LEFT :
					xPoint = (xPoint <= -10)? -10 : xPoint - 10;
					break;
				case KeyEvent.VK_RIGHT :
					xPoint = (xPoint >= 300)? 300 : xPoint + 10;
					break;
				default: 
					break;
				}
//				if(keyCode == KeyEvent.VK_UP) {
//					yPoint = (yPoint < -40)? 0 : yPoint - 10;
//					System.out.println("yPoint : " + yPoint);
//				}else if(keyCode == KeyEvent.VK_DOWN) {
//					yPoint = (yPoint > 220)? 220 : yPoint + 10;
//					System.out.println("yPoint : " + yPoint);
//				}else if(keyCode == KeyEvent.VK_LEFT) {
//					xPoint = (xPoint < -10)? -10 : xPoint - 10;
//					System.out.println("xPoint : " + xPoint);
//				}else if(keyCode == KeyEvent.VK_RIGHT) {
//					xPoint = (xPoint > 300)? 300 : xPoint + 10;
//					System.out.println("xPoint : " + xPoint);
//				}
				repaint();
			}
		});
	}
	
	private class MyImagePanel extends JPanel{
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(backgroundImage, 0, 0, 500, 500, null);
			g.drawImage(imageIcon1, xPoint, yPoint, 200, 200, null);
		}
	}
}

swicth - case문으로 변경하기 

package ch03;

import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class MyFrame8 extends JFrame{

	BufferedImage backgroundImage;
	BufferedImage imageIcon1;
	MyImagePanel imagePanel;
	int xPoint = 200;
	int yPoint = 200;
	int Point = 200;
	
	
	public MyFrame8() {
		initData();
		setInitLayout();
		addEventListener();
	}
	private void initData() {
		setTitle("이미지 백그라운드 연습 2");
		setSize(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			backgroundImage = ImageIO.read(new File("background1.jpg"));
			imageIcon1 = ImageIO.read(new File("among1.png"));
//			imageIcon1 = ImageIO.read(new File("among2.png"));
		} catch (Exception e) {
			System.err.println("파일이 없습니다.");
			System.exit(0);//프로그램을 알아서 종료시키는 명령어
		}
		
		imagePanel = new MyImagePanel();
		
	}
	private void setInitLayout() {
		this.setVisible(true);
		this.setResizable(false);//크기를 줄이거나 늘리지 못하게 막는 코드
		this.add(imagePanel);
	}
	private void addEventListener() {
				    //익명 구현 객체
		this.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				//삼항연산자로 사용해서 코드를 작성해주세요
				// 조건식 ? 결과1 : 결과2; 
				int keyCode = e. getKeyCode();
//				if(keyCode == KeyEvent.VK_UP) {
//					yPoint = (yPoint < -10)? 0 : yPoint - 10;
//					System.out.println("yPoint : " + yPoint);
//				}else if (keyCode == KeyEvent.VK_DOWN) {
//					yPoint = (yPoint > 390)? 390 : yPoint + 10;
//					System.out.println("yPoint : " + yPoint);
//				}else if (keyCode == KeyEvent.VK_LEFT) {
//					xPoint = (xPoint < -10)? 0 : xPoint - 10;
//					System.out.println("xPoint : " + xPoint);
//				}else if (keyCode == KeyEvent.VK_RIGHT) {
//					xPoint = (xPoint > 410)? 410 : xPoint + 10;
//					System.out.println("xPoint : " + xPoint);
//				}
//				repaint();
				
				//switch-case문으로 변경
				System.out.println(keyCode);
				switch (keyCode) {
				case KeyEvent.VK_UP :
					yPoint = (yPoint <= -30)? 0 : yPoint - 10;
					break;
				case KeyEvent.VK_DOWN :
					yPoint = (yPoint >= 400)? 400 : yPoint + 10;
					break;
				case KeyEvent.VK_LEFT :
					xPoint = (xPoint <= -10)? -10 : xPoint - 10;
					break;
				case KeyEvent.VK_RIGHT :
					xPoint = (xPoint >= 420)? 420 : xPoint + 10;
					break;
				default: 
					break;
				}
				repaint();
			}// end of KeyPressed
		});
	}
	
	//내부 클래스 생성
	private class MyImagePanel extends JPanel{
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(backgroundImage, 0, 0, 500, 500, null);
			g.drawImage(imageIcon1, xPoint, yPoint, 80, 80, null);
		}
	}

}//end of class
package ch03;

import java.util.Scanner;

public class MainTest1 {

	public static void main(String[] args) {
//		MyFrame7 frame7 = new MyFrame7();
		
		//외부에서 사용
//		Scanner scanner = new Scanner(System.in);
//		System.out.println("글자를 입력하세요");
//		String userInput = scanner.nextLine();
//		frame7.area.setText(userInput);
		
		//new MyFrame8();
        new MyFrame8_1();
	}
}

0.5초에 " - " 하나씩 찍히기 

package ch01;

public class ThreadTest1 {

	//main function < -- main Thread(작업자)
	public static void main(String[] args) {
		
		for (int i = 0; i < 30; i++) {
			System.out.print("-");
			//스레드 이름으로 접근해서 메서드() = static메서드        
			
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}//end of main

}//end of class

스레드 작업자 개수 알아보기

package ch01;
//멀티스레드_스레드 생성 방법
//import java.lang.*;에 Thread가 있어서 따로 임포트 하지 않아도 됨
				//1. 스레드 상속
class MyThreadEx2 extends Thread{
	
	String name;
	
	public MyThreadEx2(String name) {
		this.name = name;
	}
	//2. 약속  run , ctrl space
	@Override
	public void run() {
		int i;
		for(i = 0; i < 50; i++) {
			System.out.println(name + " : " + i + "\t");
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}//end of for
	}//end of run
}//end of MyTreadEx2

public class ThreadTest2 {
	//메인 스레드_작업자 1명
	public static void main(String[] args) {
		System.out.println(Thread.currentThread());
		System.out.println("메인 스레드 시작");
		//작업자 1명_여기까지 총 2명
		MyThreadEx2 th1 = new MyThreadEx2("작업자1");
		th1.start(); //스레드의 작업을 시작하는 명령어 입니다.
		
//		for(int i = 0; i < 50; i++) {
//			System.out.println("test : " + i);
//			try {
//				Thread.sleep(200);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}
		MyThreadEx2 th2 = new MyThreadEx2("작업자2");
		th2.start();
		MyThreadEx2 th3 = new MyThreadEx2("작업자3");
		th3.start();
		
		System.out.println("메인 스레드 종료");
		//Thread[main,5,main]
		//            ㄴ 숫자가 높을 수록 우선순위가 높다.
		
	}//end of main
}//end of class

th1.run() 으로 바로 불러오기 

package ch01;
	
class MyThread3 extends Thread{
		
	String name;
		
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println(i + " : " + Thread.currentThread());
		}
	}
		
	public MyThread3(String name) {
		this.name = name;
	}
}
		
public class ThreadTest3 {
	//메인 스레드
	public static void main(String[] args) {
		System.out.println(Thread.currentThread());
		
		//작업자 3명 생성
		MyThread3 th1 = new MyThread3("작업자1");
		MyThread3 th2 = new MyThread3("작업자2");
		MyThread3 th3 = new MyThread3("작업자3");
		//작업을 시작시켜 주세요
		th1.start();
		th2.start();
		th3.start();
		th1.run();//접근지시제어자가 public이라 사용가능
		
	}//end of main

}//end of class

Thread란?

* process : 프로그램이 실행되면 os로 부터 메모리를 할당받아 프로세스 상태가 된다.
 * thread : 하나의 프로세스는 하나 이상의 thread를 가지게 되고, 실제 작업을 
 * 수행하는 단위는 thread이다.
 * 
 * multi threading
 * 여러 thread가 동시에 수행되는 프로그래밍, 여러 작업이 동시에 실행되는 효과
 * thread는 각각 자신만의 작업 공간을 가질 수 있다. (context)
 * 
 * 여러 thread가 자원을 공유하여 작업이 수행되는 경우 서로 자원을 차지하려는
 * race condition이 발생할 수 있다. (의도하지 않은 결과를 생성할 수 있다.)
 * --> 이렇게 여러 thread가 공유하는 자원 중 경쟁이 발생하는 부분을 critical section(임계 영역)이라고 한다. 
 * 동기화 : critical section에 대한 동기화(일종의 순차적으로 수행)를 구현하게 설계 해야한다.


Runnable1

package ch01;

import javax.swing.JFrame;

//Runnable interface를 구현하여 만들면 된다.

class MyRunnable1 extends JFrame implements Runnable{

	@Override
	public void run() {
		for (int i = 0; i < 200; i++) {
			System.out.print(i+"\t");
		}
	}
}

public class RunnableTest1{
	//메인 쓰레드_ 쓰레드 1개
	public static void main(String[] args) {
		
		MyRunnable1 myRunnable1 = new MyRunnable1();

		//Runnable을 구현한 객체는 Thread를 생성해서 매개변수에 담고 쓰레드를 시작한다.
		//작업자 1_쓰레드 2개 (멀티쓰레딩)
		Thread thread1 = new Thread(myRunnable1);
		thread1.start();
		
		Thread thread2 = new Thread(myRunnable1);
		thread2.start();
	}
}

객체 생성과 동시에 run메서드 실행, 외부에서 run 메서드 동작 Runnable2

package ch01;

import javax.swing.JFrame;

class MyRunnable2 extends JFrame{
	
	int grade = 10;
	
	public MyRunnable2() {
		runnable.run();
	}

	//익명 구현 객체 모양
//	new Runnable() {
//		
//		@Override
//		public void run() {
//			// TODO Auto-generated method stub
//			
//		}
//	};
	// 자바 문법

	// 구현 객체
	Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			for (int i = 0; i < grade; i++) {
				System.out.print("--");
			}
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}//end of for
			
		}//end of run
	};
}

public class RunnableTest2 {

	public static void main(String[] args) {
		
		MyRunnable2 myRunnable2 = new MyRunnable2();
		//문제 1. 객체 생성과 동시에 run 메서드를 실행 시켜 주세요.
		//문제2. 외부에서 run 메서드 동작 시켜 주세요.
		myRunnable2.runnable.run();
	}
}

Thread do while

package ch02;

import java.util.Scanner;

class MyThread1 extends Thread {
	
	boolean flag = true;
	
	@Override
	public void run() {
		while (flag) {
			System.out.print("-");
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}// end of run

}// end of class

public class ThreadEx1 {

	public static void main(String[] args) {

		System.out.println("작업자를 생성하겠습니다.");
		//메인스레드가 작업자를 요청해서 생성
		MyThread1 thread1 = new MyThread1();
		thread1.start();
		
		System.out.println("0번을 입력하면 중지 합니다.");
		Scanner scanner = new Scanner(System.in);
//		int userInput = scanner.nextInt();
//		
//		if(userInput == 0) {
//			thread1.stop();// deprecated (더이상 유지 보수 하지 않음)
//			thread1.flag =false;
//		}
		//문제 3.
		//do while사용해서 사용자가 한번 입력을 하더라도 
		//다시 입력을 받을 수 있게 코드를 만들어 주세요
		
		//1. do while문 사용방법
		//2. do 안에 어떤 코드가 들어갈지 생각해서 작성
		//3. while 문에 조건식을 구현

		int userInput;
		do {
			userInput = scanner.nextInt();
			if(userInput == 0) {
				thread1.flag =false;
			}
		}while(userInput != 0);
		
	}

}