: 실행 중인 program
: 프로그램이 실행되려면 OS
로부터 resource
(자원)
Resouce : code, Data, Heap, Stack
java 프로그램에서 code를 작성한다 = ~.java
Javac.complier를 이용해서 compile을 함 => bytecode 생김 (~.class file)
-> Java interpreter 실행
-> JVM(얘도 프로세스 = 여러 thread가 숨어 있음 ex)garbage collector가 지켜보다가 발견하면 청소함)
-> JVM이 내부에 내 프로그램을 수행시키기 위한 별도의 Thread 생성 = main thread
-> main thread 는 main() method 호출
Java에서 Thread 생성 -> 실행 -> 어떤 code를 수행함 ( run() method 안에 있어야함)
방법
1. Thread class 상속
class A extends Thread {
@Override
run(){
}
}
=>
A a = new A();
a.start() //Thread를 실행가능한 형태인 Runnable 상태로 전환
2. Runnable interface를 구현한 객체를 이용
class A implements Runnable {
@Override
run(){
}
}
=>
A r= new A(); // Runnable r = new A(); 도 가능. is-a 관계에 의해
Thread a = new Thread(r) // r에 run 메소드를 가지고 있는 인자를 넣음)
a.start();
=> main thread 1개만 이용
single thread
: 실행 흐름이 1개이기 때문에 순차처리
=> 처리가 안 되는 경우가 많고
=> 처리가 되더라도 효율성이 너무 낮음
multi thread
: 다중thread
를 이용해서 해결
new - start()
: static method
: 특정 지정 못함. 현재 !
start() : 시작 method
suspend() : 일시정지 method
resume() : 다시 실행 method(일시정지된 후)
stop() : 종료 method
dead-lock 자주 발생하여 deprecated 되기 때문에 쓰면 안 됨
그러면 어떤 method를 이용하나요? 아래와 같은 로직으로 처리함
package sampleproj;
import javax.swing.JOptionPane;
class ThreadEx_06_1 extends Thread {
@Override
public void run() {
int i = 10; // 지역변수
while(i != 0) {
System.out.println(i--); // 10출력 후 i값을 1감소
}
System.out.println("카운트가 종료되었습니다.");
}
}
public class ThreadEx_06 {
public static void main(String[] args) {
Thread t = new ThreadEx_06_1(); // thread instance 생성
// t.start(); // thread를 Runnable상태로 전이시킴
// 바로 실행은 안 되지만, 언젠가는 Thread Scheduler에 의해 실행됨
String data = JOptionPane.showInputDialog("값을 입력하세요.");
//JOptionPane은 class, showInputDialog는 static으로 지정됨
System.out.println(data);
}
}//
package sampleproj;
import javax.swing.JOptionPane;
class ThreadEx_06_1 extends Thread {
@Override
public void run() {
int i = 10; // 지역변수
while(i != 0) {
System.out.println(i--); // 10출력 후 i값을 1감소
// busy-waiting
for(long k=0; k<100000000000000000L; k++);
}
System.out.println("카운트가 종료되었습니다.");
}
}
public class ThreadEx_06 {
public static void main(String[] args) {
Thread t = new ThreadEx_06_1(); // thread instance 생성
t.start(); // thread를 Runnable상태로 전이시킴
// 바로 실행은 안 되지만
// 언젠가는 Thread Scheduler에 의해 실행됨
String data = JOptionPane.showInputDialog("값을 입력하세요.");
//JOptionPane은 class, showInputDialog는 static으로 지정됨
System.out.println(data);
}
}//
카운트가 천천히 떨어짐
t.suspend();
package sampleproj;
import javax.swing.JOptionPane;
class ThreadEx_06_1 extends Thread {
@Override
public void run() {
int i = 10; // 지역변수
while(i != 0 && !isInterrupted()) { // this.isInterrupted에서 this. 생략
System.out.println(i--); // 10출력 후 i값을 1감소
// busy-waiting
for(long k=0; k<300000000000000000L; k++);
}
System.out.println("카운트가 종료되었습니다.");
}
}
public class ThreadEx_06 {
public static void main(String[] args) {
Thread t = new ThreadEx_06_1(); // thread instance 생성
t.start(); // thread를 Runnable상태로 전이시킴
// 바로 실행은 안 되지만
// 언젠가는 Thread Scheduler에 의해 실행됨
String data = JOptionPane.showInputDialog("값을 입력하세요.");
//JOptionPane은 class, showInputDialog는 static으로 지정됨
System.out.println(data);
t.interrupt(); // thread를 interrupt 시켰음
// thread가 중지/일지정지 등은 발생하지 않음
// 로직으로 thread의 행동을 제어해야 함
// t.suspend();
// t.stop();
}
}//
- java에서 method
: 무조건class명/instance
.method명()/field
: 일반변수(local variable)은 당연히 혼자 나옴- but, method/field 명이 그냥 달랑 혼자 나오는 경우가 있음
:this.
생략된 것
t.interrupt(); 로 stop과 같은
package sampleproj;
import javax.swing.JOptionPane;
class ThreadEx_06_1_part1 extends Thread {
@Override
public void run() {
int i = 10; // 지역변수
while(i != 0 && !this.isInterrupted()) { // this.isInterrupted에서 this. 생략
System.out.println(i--); // 10출력 후 i값을 1감소
try {
Thread.sleep(2000);
} catch(InterruptedException e){
// interrupt();
System.out.println("앗, 자는 중에 interrupt가 걸렸어요");
}
}
System.out.println("카운트가 종료되었습니다.");
}
}
public class ThreadEx_06_part1 {
public static void main(String[] args) {
Thread t = new ThreadEx_06_1(); // thread instance 생성
t.start(); // thread를 Runnable상태로 전이시킴
// 바로 실행은 안 되지만
// 언젠가는 Thread Scheduler에 의해 실행됨
String data = JOptionPane.showInputDialog("값을 입력하세요.");
System.out.println(data);
t.interrupt(); // thread를 interrupt 시켰음
// thread가 중지/일지정지 등은 발생하지 않음
// 로직으로 thread의 행동을 제어해야 함
// 만약 interrupt를 걸었는데 이때 해당 Thread가
// sleep상태면,,
}
}//
package sampleproj;
class ThreadEx_07_1 implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()); // 현재Thread를 찾는다
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
public class ThreadEx_07 {
public static void main(String[] args) {
// Runnable interface를 구현한 class의 instance를 생성
Runnable r = new ThreadEx_07_1();
Thread t1 = new Thread(r, "*"); //하는 일이 없기때문에 하는 일이 있는 r를 넣어줌
Thread t2 = new Thread(r, "**");
Thread t3 = new Thread(r, "***");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(2000); //main thread가 졸게 된다
} catch (Exception e) {
// TODO: handle exception
}
}
}
t1 suspend
package sampleproj;
class ThreadEx_07_1 implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()); // 현재Thread를 찾는다
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
public class ThreadEx_07 {
public static void main(String[] args) {
// Runnable interface를 구현한 class의 instance를 생성
Runnable r = new ThreadEx_07_1();
Thread t1 = new Thread(r, "*"); //하는 일이 없기때문에 하는 일이 있는 r를 넣어줌
Thread t2 = new Thread(r, "**");
Thread t3 = new Thread(r, "***");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(2000); //main thread가 졸게 된다
t1.suspend(); //t1을 일시정지
} catch (Exception e) {
// TODO: handle exception
}
}
}
try {
Thread.sleep(2000); //main thread가 졸게 된다
t1.suspend(); //t1을 일시정지
Thread.sleep(2000);
t2.suspend();
} catch (Exception e) {
// TODO: handle exception
}
try {
Thread.sleep(2000); //main thread가 졸게 된다
t1.suspend(); //t1을 일시정지
Thread.sleep(2000);
t2.suspend();
Thread.sleep(2000);
t1.resume();
} catch (Exception e) {
// TODO: handle exception
}
try {
Thread.sleep(2000); //main thread가 졸게 된다
t1.suspend(); //t1을 일시정지
Thread.sleep(2000);
t2.suspend();
Thread.sleep(2000);
t1.resume();
Thread.sleep(2000);
t1.stop();
t2.stop();
Thread.sleep(2000);
t3.stop();
} catch (Exception e) {
// TODO: handle exception
}
package sampleproj;
class ThreadEx_08_1 implements Runnable{
//자체적으로 필드를 가짐
boolean suspended = false;
boolean stopped = false;
@Override
public void run() {
while(!stopped) {
if(!suspended) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
public void suspend() { suspended = true; }
public void resume() { suspended = false; }
public void stop() { stopped = true; }
}
public class ThreadEx_08 {
public static void main(String[] args) {
// Runnable 객체를 공유하면 안됨 !
ThreadEx_08_1 r1 = new ThreadEx_08_1();
ThreadEx_08_1 r2 = new ThreadEx_08_1();
ThreadEx_08_1 r3 = new ThreadEx_08_1();
Thread t1 = new Thread(r1, "*");
Thread t2 = new Thread(r1, "**");
Thread t3 = new Thread(r1, "***");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(2000); // main thread sleep
// 첫번째 thread를 일시정지할 거에요
// Thread를 직접제어하지 않고 Thread가 가지고 있는 Runnable 객체의
// field값을 조절해서 Runnable객체가 가지고 있는 run() method의
// 로직을 변화시키는 거에요
r1.suspend(); // thread를 제어하는게 아님. t1.suspend()
} catch (Exception e) {
}
}
}
volatile boolean suspended = false; volatile boolean stopped = false;
하면 제대로 나옴
package sampleproj;
class ThreadEx_08_1 implements Runnable{
//자체적으로 필드를 가짐
volatile boolean suspended = false;
volatile boolean stopped = false;
@Override
public void run() {
while(!stopped) {
if(!suspended) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
public void suspend() { suspended = true; }
public void resume() { suspended = false; }
public void stop() { stopped = true; }
}
public class ThreadEx_08 {
public static void main(String[] args) {
// Runnable 객체를 공유하면 안됨 !
ThreadEx_08_1 r1 = new ThreadEx_08_1();
ThreadEx_08_1 r2 = new ThreadEx_08_1();
ThreadEx_08_1 r3 = new ThreadEx_08_1();
Thread t1 = new Thread(r1, "*");
Thread t2 = new Thread(r1, "**");
Thread t3 = new Thread(r1, "***");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(2000); // main thread sleep
// 첫번째 thread를 일시정지할 거에요
// Thread를 직접제어하지 않고 Thread가 가지고 있는 Runnable 객체의
// field값을 조절해서 Runnable객체가 가지고 있는 run() method의
// 로직을 변화시키는 거에요
r1.suspend(); // thread를 제어하는게 아님. t1.suspend()
Thread.sleep(2000);
r2.suspend();
Thread.sleep(2000);
r1.resume(); // 이거 왜 안 나오는지? 로직은 문제 없는 것 같음..
Thread.sleep(2000);
r1.stop();
r2.stop();
Thread.sleep(2000);
r3.stop();
} catch (Exception e) {
}
}
}
로직을(while, if 변수쿼리) 이용해서 Thread의 동작 제어 :
일시정지
,다시시작
,중지
yield()
: 프로그램은 조금 더 효율적으로 작성!
1초 동안 수행하세요 0.5초->양보
package sampleproj;
class ThreadEx_09_1 implements Runnable{
//자체적으로 필드를 가짐
volatile boolean suspended = false;
volatile boolean stopped = false;
Thread t; //내가 가지고 있는 field
void setThread(Thread t) {
this.t = t;
}
@Override
public void run() {
while(!stopped) {
if(!suspended) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
} else {
Thread.yield();
}
}
}
public void suspend() {
suspended = true;
// 아마도 최대 1초 뒤에 상태를 확인해서 일시중지 작업을 시행함
// 최대한 빨리 일시중지 상태에 돌입하려면 현재 thread에 대해서 interrupt를 걸어야 함
t.interrupt(); //내가 가진 field를 interrupt
}
public void resume() { suspended = false; }
public void stop() {
stopped = true;
t.interrupt();
}
}
public class ThreadEx_09 {
public static void main(String[] args) {
// Runnable 객체를 공유하면 안됨 !
ThreadEx_09_1 r1 = new ThreadEx_09_1();
ThreadEx_09_1 r2 = new ThreadEx_09_1();
ThreadEx_09_1 r3 = new ThreadEx_09_1();
Thread t1 = new Thread(r1, "*");
Thread t2 = new Thread(r1, "**");
Thread t3 = new Thread(r1, "***");
r1.setThread(t1);
r2.setThread(t2);
r3.setThread(t3);
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(2000); // main thread sleep
// 첫번째 thread를 일시정지할 거에요
// Thread를 직접제어하지 않고 Thread가 가지고 있는 Runnable 객체의
// field값을 조절해서 Runnable객체가 가지고 있는 run() method의
// 로직을 변화시키는 거에요
r1.suspend(); // thread를 제어하는게 아님. t1.suspend()
Thread.sleep(2000);
r2.suspend();
Thread.sleep(2000);
r1.resume(); // 이거 왜 안 나오는지? 로직은 문제 없는 것 같음..
Thread.sleep(2000);
r1.stop();
r2.stop();
Thread.sleep(2000);
r3.stop();
} catch (Exception e) {
}
}
}
: join()
: join(millisecond로)
: join은 instance method 특정 thread를 포함시킬 수 있음
package sampleproj;
class ThreadEx_10_1 extends Thread {
@Override
public void run() {
for(int i=0; i<100; i++) {
System.out.print("-");
}
}
}//
class ThreadEx_10_2 extends Thread {
@Override
public void run() {
for(int i=0; i<100; i++) {
System.out.print("|");
}
}
}//
public class ThreadEx_10 {
public static void main(String[] args) {
long startTime = 0; // 시간체크해보려고 넣음
Thread t1 = new ThreadEx_10_1();
Thread t2 = new ThreadEx_10_2();
t1.start();
t2.start();
startTime = System.currentTimeMillis(); //숫자로 현지시간을 표현 (밀리세컨즈단위)
try {
t1.join(); // t1이 끝날 때까지 main을 멈추고, t1이 끝나면 main 다시 실행
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("소요시간 : " + (System.currentTimeMillis() - startTime));
}
}//
main()이 맨 마지막에 실행됨
package sampleproj;
class ThreadEx_11_1 extends Thread{
// 상수 필드를 하나 선언할 거에요
// 상수 필드는 관용적으로 대문자를 사용하고 snake case를 이용
final static int MAX_MEMORY = 1000;
int usedMemory = 0;
@Override
public void run() {
while(true) {
try {
Thread.sleep(10000); // 10초간 잔다
} catch (Exception e) {
}
gc(); // memory 청소해서 memory용량을 다시 확보하는 method
System.out.println("남음 메모리량 : freemehod");
}
}
private void gc() {
usedMemory = usedMemory - 300;
if(usedMemory < 0) {
usedMemory = 0;
}
}
public int totalMemory() {
return MAX_MEMORY;
}
public int freeMemory() { // 전체 메모리에서 사용된 메모리량을 빼서
// 현재 가용한 메모리량을 알아냄
return MAX_MEMORY - usedMemory;
}
}
public class ThreadEx_11 {
public static void main(String[] args) {
}
}