★ Thread: 쓰레드를 이용하면 한 프로세스 내에서 (동시에 여러 작업을 처리하는 문법)
: extends Thread //쓰레드 상속하면 run 메서드를 구현해야함.
: start()로 쓰레드를 실행한다.
★ Process: 동작하고 있는 프로그램
★ Task
작업단위
★ (작업자,사장 ) Main Thread
★ (상속 :일꾼, 직원) Thread - run() 메서드 작업 수행.
Thread 상속
Runnable구현
My Thread
비동기. 동기방식
extends Thread = run override
: sleep (try-catch문) (5000); 5초간격으로
main Thread = start
ThreadA a = new ThreadA();
a.start(); //자동으로 run 메소드가 발동함.
ThreadB b = new ThreadB();
b.start(); //자동으로 run 메소드가 발동함.
public class Main {
public static void main(String[] args) {
//Thread(스레드) : 동시에 여러 작업을 처리하는 기법 **프로세스 쓰레드 차이점 면접**
//1. Process : 실행중인 하나의 자바 프로그램 [본인만의 메모리영역을 가짐(Method, Stack, Heap)]
// -프로세스간에는 자원공유 불가
//2. Thread : 하나의 프로세스안에서 동작하는 일꾼(직원)같은 개념
// - 하나의 프로세스안에서 스레드간에는 *자원공유 가능*
//즉, Thread는 작성되어 있는 코드를 읽어서 실행하는 녀석으로 생각하면 됨.
//하나의 프로세스에는 적어도 하나의 스레드가 기본적으로 존재하며 이 스레드를 Main Thread 라고 부름(사장같은 개념)
//동시에 했으면 하는 작업 2개 구현
//ex) 파일 다운로드 하면서 음악재생 or 채팅하기 etc...
//아직 네트워크는 배우지 않았으니.. 그냥 느낌만..
//20개의 파일을 다운로드하는 작업..
// for(int i=0; i<20; i++) {
// System.out.println(i+ "번 파일 다운로드 중...");
//
// //강제로 시간이 걸리는 느낌 가지도록..
// for(int k=0; k<2000000000; k++) {
// new String("aaa");
// new String("aaa");
// new String("aaa");
// new String("aaa");
// }
// }
//20개의 음악을 재생하는 작업..
// for (int i=0; i<20; i++) {
// System.out.println(i+"번 음악 재생~~");
// for(int k=0; k<2000000000; k++) {
// new String("aaa");
// new String("aaa");
// new String("aaa");
// new String("aaa");
// }
// }
//Main Thread가 혼자서 위 코드를 읽어서 실행하기에
//동시에 실행되지 않고 차례대로 실행됨.
//동시에 하려면?? 별도의 직원(Thread의 능력을 가진)객체가 필요함.
//이 직원이 해야할 작업(Task)을 작성해놓은 클래스를 설계
// 직원채용- Thread 객체 생성
ThreadA a= new ThreadA();
//a.run(); //직접run()메소드를 호출하면 이 작업은 Main Thread가 함
//스레드의 run()메소드 실행은 반드시 start()라는 명령으로 실행해야 함 ***********
a.start(); //자동으로 run()메소드가 발동함
ThreadB b=new ThreadB();
b.start();
//Main Thread도 별도의 작업을 동시에 수행하고 싶다면.
for(int i =100; i<120; i++) {
String name = Thread.currentThread().getName();
System.out.println(name+ ":" + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}//main method..
}//main class..
//파일 다운로드 작업을 수행하는 직원 클래스 - Thread의 능력을 가진..
class ThreadA extends Thread{
//모든 Thread클래스의 작업은 반드시 이 메소드안에서 작성 해야만 함.
//Thread클래스 안에 원래 있는 run()메소드를 오버라이드 해서 사용해야만 함.
@Override
public void run() {
for(int i=0; i<20; i++) {
System.out.println(i+ "번 파일 다운로드 중...");
String name= Thread.currentThread().getName();
System.out.println(name+ ":" + i+"번 다운로드~");
//현재 스레드를 0.5초간(1000ms) 잠재우기
try {
Thread.sleep(500);// sleep **
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//강제로 시간이 걸리는 느낌 가지도록..
// for(int k=0; k<2000000000; k++) {
// new String("aaa");
// new String("aaa");
// new String("aaa");
// new String("aaa");
// }
}
}
}
//음악 재생 작업을 수행하는 직원 클래스 - Thread의 능력을 가진..
class ThreadB extends Thread{
@Override
public void run() {
for (int i=0; i<20; i++) {
System.out.println(i+"번 음악 재생~~");
String name = Thread.currentThread().getName();
System.out.println(name+ ":" + i+"번 음악재생~~");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// for(int k=0; k<2000000000; k++) {
// new String("aaa");
// new String("aaa");
// new String("aaa");
// new String("aaa");
// }
}
}
}
--------------------------------------------------------------------------------------------
public class RunnableTest {
public static void main(String[] args) {
//Thread 만드는 2가지 방법
//1. Thread클래스를 상속하는 클래스를 설계하여 사용
//2. Runnable인터페이스를 구현하는 클래스를 설계하여 사용
//인터페이스가 존재하는 이유가 뭘까?
//다중 상속의 효과를 보고 싶어서..
//Person클래스의 능력을 가지면서.. 동시에 스레드의 능력도 보유한 객체를 생성
PersonThread pt=new PersonThread();
pt.name="sam";
pt.age=20;
//스레드의 기능 run()메소드가 실행되도록..
//pt.stat(); //error -- Runnable은 start()기능이 없음.
//pt.run();//이 작업은 Main Thread가 수행함.
//Runnable로 만든 스레드객체는 start를 시켜주는 별도의
//trigger용 Thread객체가 필요함.
Thread t= new Thread(pt); //생성자에 Runnable객체를 전달
t.start(); //대신 start.. 생성자로 받은 Runnable객체의 run()메소드가 발동됨
System.out.println("메인 스레드 작업");
//클래스를 만들어놓으면 언제든 new만 쓰면 여러개의 객체를 만들 수 있음.
PersonThread pt2= new PersonThread();
PersonThread pt3= new PersonThread();
//Runnable 인터페이스를 구현한 클래스의 이름을 매번 정하는것이
//은근 짜증 .. 만약 그 클래스가 1번만 객체로 만들어서 사용될것이라면
//별도의 클래스.Jave파일로 만드는 것이 더 짜증 !!~비효율적임.
//그래서 1회용 설계도를 이용하면 이를 해결함.
//객체를 생성하면서 설계하는 문법을 이용할 것임.
//이름이 없는 클래스 -- 익명클래스 라고 부름 **GUI에서 많이 사용!!
Runnable r=new Runnable() {
@Override
public void run() {
System.out.println("runnable...");
}
};
Thread tt = new Thread(r);
tt.start();
//위 코드를 더 줄여서..
Thread ttt= new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("익명 클래스...");
}
});
ttt.start();
//GUI에서 많이 사용함 **
new Thread() {
public void run() {
System.out.println("스레드 상속한 익명클래스");
}
}.start();
}
}//main
class PersonThread extends Person implements Runnable{
@Override
public void run() {
for (int i=0; i<5; i++) {
System.out.println(name+ " : " + age);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Person{
String name;
int age;
}
--------------------------------------------------------------------------------------------
public class RaceHorseTest {
public static void main(String[] args) {
Horse h1 = new Horse("캐논");
Horse h2 = new Horse("천리안");
Horse h3 = new Horse("적토마");
System.out.println("경주시작");
h1.start();
h2.start();
h3.start();
h1.setPriority(10); //높은 우선권
h2.setPriority(2);
}
}
class Horse extends Thread{
String name;
//생성자
public Horse(String name) {
this.name =name;
}
@Override
public void run() {
for(int i=0; i<20; i++) {
System.out.println(name +": 다그닥!!다그닥!!");
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//for
System.out.println(name+ "도착");
}
}
--------------------------------------------------------------------------------------------
public class SunchronizedTest {
public static void main(String[] args) {
//동기화 처리 - Thread를 사용하는 것은 비동기 처리를 한다는 것임.
//동기 (Synchronize) : a 작업이 끝나면 b 작업 하는 것.
//비동기 (Asynchronize) : a 작업을 할때 b 작업도 동시에 하는 것.
//계좌 객체
Account acc= new Account();
//acc계좌에 100원을 입금하고 싶은 고객1 - Thread
CustomerThread t1= new CustomerThread(acc);
//acc계좌에 100원을 입금하고 싶은 고객2 - Thread
CustomerThread t2= new CustomerThread(acc);
//비슷한 시점에 둘다 100원을 입금 동작 실행!
t1.start(); //run()메소드 자동 발동!
t2.start();
}
}
//은행계좌 클래스
class Account{
int money= 0;
//입금기능 - 동기화처리 되지 않은 기능
//이 add()기능을 동기화 처리하지 않으면 여러 Thread가 동시에 기능을 발동하여 문제를 야기할 수 있음.
//이를 해결하기 위해 동기화 처리를 함. 방법 2가지 존재함.
// void add(int m) {
// System.out.println("입금 작업을 시작합니다.");
//
// String name= Thread.currentThread().getName();
// System.out.println(name + " - 현재 잔액 : " + money);
//
// //입금기능 코드
// money= money+m;
// //일부러 전산처리 시간을 가정하여 오래걸리는 작업 코드.
// for (long i=0;i<45000000000L; i++) {
// new String("aaa");
// }////////////////////////////////시간버는 용
//
// System.out.println(name+ " - 입금 후 잔액 : "+ money);
// System.out.println();
//
// }
//방법1. 이add()기능 메소드 자체를 동기화 처리
// synchronized void add(int m) {
// System.out.println("입금 작업을 시작합니다.");
//
// String name= Thread.currentThread().getName();
// System.out.println(name + " - 현재 잔액 : " + money);
//
// //입금기능 코드
// money= money+m;
// //일부러 전산처리 시간을 가정하여 오래걸리는 작업 코드.
// for (long i=0;i<45000000000L; i++) {
// new String("aaa");
// }////////////////////////////////시간버는 용
//
// System.out.println(name+ " - 입금 후 잔액 : "+ money);
// System.out.println();
//
// }
//방법2. 동기화 블럭
void add(int m) {
System.out.println("입금 작업을 시작합니다.");
//동기화 블럭(보호할 것) -Thread의 기능을 감소시킴 synchronized() :rock걸렸다.
synchronized(this) {
String name= Thread.currentThread().getName();
System.out.println(name + " - 현재 잔액 : " + money);
//입금기능 코드
money= money+m;
//일부러 전산처리 시간을 가정하여 오래걸리는 작업 코드.
for (long i=0;i<45000000000L; i++) {
new String("aaa");
}////////////////////////////////시간버는 용
System.out.println(name+ " - 입금 후 잔액 : "+ money);
System.out.println();
}
}
}
//계좌에 돈을 입금하는 동작을 수행하는 Thread클래스 설계
class CustomerThread extends Thread{
Account acc;
//constructor
public CustomerThread(Account acc) {
this.acc= acc;
}
@Override
public void run() {
acc.add(100); //100원을 입금하는 동작 수행
}
}
-------------------------------------------------------------------------------------------
public class ThreadControlTest {
public static void main(String[] args) {
//게임만들때 쓰임. Thread많이 사용.**
//타이어조립 직원객체 생성
CThread t=new CThread();
t.start(); //Thread는 딱 1번만 start()실행 가능. ******
//t.start();
//t.start();//error
//3초 후에 휴식.. 즉, 스레드의 일시정지
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//t.wait(); //직접 wait()을 권장하지 않음.
t.pauseThread();
//3초 후에 휴식 끝. 작업개시 .. 즉, 스레드 이어하기
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//wait()으로 일시정지된 스레드를 깨워야 함.
//t.notify(); //직접 notify()를 권장하지 않음
//t.resumeThread();
//3초 후에 퇴근..즉, 스레드 종료
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//t.stop(); //동작은 되지만 권장하진 않는 문법.
//강제로 스레드를 멈추지 말고 자연스럽게
//run()메소드가 종료되도록 해야함.
//while문에 의해 run()이 안끝나고 있으니
//while문만 종료시키면 됨
//while문의 반복조건 변수인 isRun을 false로 변경
//t.isRun= false;
//객체지향프로그래밍 방법론에서는 가급적 객체의 멤버변수는
//직접 제어하지 않는 것을 권장함.
//메소드를 이용하여 멤버변수의 값 변경을 권장함.
t.stopTherad();
}//Main method..
}//class..
//특정 작업을 수행하는 직원(Thread) 클래스
class CThread extends Thread{
private boolean isRun= true;
private boolean isWait= false;
@Override
public void run() {
//for문은 수행갯수를 알수있을때 사용
while(isRun) {
//작업 Task 단위
System.out.println("1번 타이어 조립");
System.out.println("2번 타이어 조립");
System.out.println("3번 타이어 조립");
System.out.println("4번 타이어 조립");
System.out.println();
if(isWait) {
//필수로 동기화 처리를 해야함.
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//반복문이 너무 빨리 처리되어서..1초간 잠시 정지
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//while..
System.out.println("\n퇴근!!\n");
}//run method..
//Thread를 안전하게 종료하는 기능메소드 정의
public void stopTherad() {
this.isRun= false;
}
//스레드를 안전하게 일시정지 하는 기능메소드 정의
public void pauseThread() {
this.isWait= true;
}
//스레드의 일시정지상태를 안전하게 깨우기
public void resumeThread() {
this.isWait=false;
//반드시 동기화 처리를 같이 해야 함
synchronized(this) {
this.notify(); //wait된 스레드를 깨움.
}
}
}//CThread class..
'JAVA' 카테고리의 다른 글
파일 입출력: Data의 영구적인 저장 (0) | 2023.08.30 |
---|---|
조건문(if, witch), 반복문(while, for), 기타제어문(break, continue) (0) | 2023.08.30 |
Collection API: List, Set, Map (2) | 2023.08.30 |
Generic (0) | 2023.08.30 |
예외처리: try-catch-finally, throws, throw (0) | 2023.07.15 |