static void sleep(long millis) // 천분의 일초 단위
static void sleep(long millis, int nanos) // 천분의 일초 + 나노초
InterruptedException
이 발생하면 깨어남)try{
Thread.sleep(1, 5000000); // 쓰레드를 0.0015초 동안 멈추게 한다.
} catch (InterruptedException e) {} // Exception의 자손, 예외처리는 필수적!
void delay(long millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException e) {}
}
try{
th1.sleep(2000); // 다른 thread를 잠자게 할 수 없다!
} catch(InterruptedException e) {}
public class Ex13_8 {
public static void main(String[] args) {
ThreadEx8_1 t1 = new ThreadEx8_1();
ThreadEx8_2 t2 = new ThreadEx8_2();
t1.start();
t2.start();
delay(2*1000);
System.out.println("<<main 종료>>");
}
static void delay(long millis){
try{
// t1.sleep(2000); // t1을 2초동안 잠자게 ?? -> main 스레드가 잠듦
Thread.sleep(millis);
} catch (InterruptedException e){}
}
}
class ThreadEx8_1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 300; i++) {
System.out.print("-");
}
System.out.printf("\n<<t1 종료>>\n");
}
}
class ThreadEx8_2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 300; i++) {
System.out.print("|");
}
System.out.printf("\n<<t2 종료>>\n");
}
}
delay()
를 주석처리한다면, main 스레드는 가장 먼저 종료된다. (t1, t2 start 이후 하는게 없기 때문)sleep()
, join()
, wait()
등의 메서드들에 의해 쓰레드가 중단됨)void interrupt() : 쓰레드의 interrupted 상태를 false에서 true로 변경
boolean isInterrupted() : 쓰레드의 interrupted 상태를 반환.(내가 잠을 다 자고 일어난건지, 중간에 누가 깨워서 일어난건지 파악이 가능)
static boolean interrupted() : 현재 쓰레드의 interrupted 상태를 알려주고, false로 interrupted 상태를 초기화
import javax.swing.*;
public class Ex13_9 {
public static void main(String[] args) {
ThreadEx9_1 th1 = new ThreadEx9_1();
th1.start();
System.out.println("isInterrupted(): " + th1.isInterrupted()); // false
String input = JOptionPane.showInputDialog("아무 값이나 입력하세요");
System.out.println("읿력하신 값은 "+input+"입니다.");
th1.interrupt();
// System.out.println("isInterrupted(): " + th1.isInterrupted()); // true
// System.out.println("isInterrupted(): " + th1.isInterrupted()); // true
// System.out.println("interrupted(): " + Thread.interrupted()); // false - 현재 쓰레드는 main 쓰레드임.
}
}
class ThreadEx9_1 extends Thread{
@Override
public void run() {
int i = 10;
while (i != 0 && !isInterrupted()) {
System.out.println(i--);
for(long x=0; x<25000000000L; x++); // 시간 지연
}
System.out.println("isInterrupted(): " + this.isInterrupted()); // true
System.out.println(" "+Thread.interrupted()); // true
System.out.println(" "+Thread.interrupted()); // false
System.out.println("카운트가 종료되었습니다.");
}
}
isInterrupted()
와는 달리 interrupted()
는 interrupted
라는 상태변수를 false로 초기화한다.public class ThreadEx17_1 implements Runnable{
boolean suspended = false;
boolean stopped = false;
@Override
public void run(){
while(!stopped){
if(!suspended){
// 쓰레드가 수행할 코드를 작성
}
}
}
public void suspend(){suspended = true;}
public void resume(){suspended = false;}
public void stop(){stopped = true;}
}
public class Ex13_10 {
public static void main(String[] args) {
MyThread th1 = new MyThread("*");
MyThread th2 = new MyThread("**");
MyThread th3 = new MyThread("***");
th1.start();
th2.start();
th3.start();
try{
Thread.sleep(2000);
th1.suspended();
Thread.sleep(2000);
th2.suspended();
Thread.sleep(3000);
th1.resume();
Thread.sleep(3000);
th1.stop();
th2.stop();
Thread.sleep(2000);
th3.stop();
} catch (InterruptedException e){}
}
}
class MyThread implements Runnable{
volatile boolean suspended = false; // volatile : 쉽게 바뀌는 변수라는 의미
volatile boolean stopped = false; // volatile 을 붙이는 이유 : CPU 코어가 여러개 존재하는데, 그 코어 안에 cache가 존재함. 복사본을 사용하지 못하게 함으로써 값을 보존
Thread th;
MyThread(String name){
th = new Thread(this, name); // Thread(Runnable r, String name)
}
void start(){
th.start();
}
void stop(){
stopped = true;
}
void suspended(){
suspended = true;
}
void resume(){
suspended = false;
}
@Override
public void run() {
while (!stopped){
if(!suspended){
System.out.println(Thread.currentThread().getName());
try{
Thread.sleep(1000);
} catch (InterruptedException e){}
}
}
}
}
void join() : 작업이 모두 끝날 때 까지
void join(long millis) : 천분의 일초 동안
void join(long millis, int nanos) : 천분의 일초 + 나노초 동안
InterruptedException
이 발생하면 작업 재개)public class Ex13_11 {
static long startTime = 0;
public static void main(String[] args) {
ThreadEx11_1 th1 = new ThreadEx11_1();
ThreadEx11_2 th2 = new ThreadEx11_2();
th1.start();
th2.start();
startTime = System.currentTimeMillis();
try {
th1.join(); // main 쓰레드가 th1의 작업이 끝날 때까지 기다린다.
th2.join(); // main 쓰레드가 th2의 작업이 끝날 때까지 기다린다.
} catch (InterruptedException e){
}
System.out.println();
System.out.println("소요시간 : "+(System.currentTimeMillis() - startTime));
}
}
public void run() {
while(true){
try{
Thread.sleep(10*1000); // 10초를 기다린다
} catch(InterruptedException e){
System.out.println("Awaken by interrupt().");
}
gc(); // garbage collection을 수행한다.
System.out.println("Garbate Collected. Free Memory : "+ freeMemory());
}
}
for(int i=0; i < 20; i++){
requiredMemory = (int)(Math.random() *10) *20;
// 필요한 메모리가 사용할 수 있는 양보다 더 적거나, 전체 메모리의 60% 이상 사용했을 경우 gc를 깨운다.
if(gc.freeMemory() < requireMemory ||
gc.freeMemorty() < gc.totalMemory() * 0.4)
{
gc.interrupt(); // 잠자고 있는 쓰레드 gc를 깨운다.
try { // 깨우기만 하면, 바로 메모리에 못 쓰기 때문에 꼭 join을 해줘야 한다.(gc() 수행시간 확보)
gc.join(100); // gc가 메모리 정리할 시간 확보
} catch (InterruptedException e) {}
}
gc.usedMemory += requiredMemory;
System.out.println("usedMemory:"+gc.usedMemory);
}
busy-waiting
상태가 된다.public class MyThreadEx18 implements Runnable{
boolean suspended = false;
boolean stopped = false;
Thread th;
MyThreadEx18(String name){
th = new Thread(this, name);
}
public void run() {
while (!stopped) {
if (!suspended) {
// 작업 수행
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
} else {
Thread.yield();
}
}
}
public void start(){th.start();}
public void resume(){suspended=false;}
public void suspend() {
suspended = true;
th.interrupt(); // 깨워야 바로 반영됨 (응답성이 좋아짐)
}
public void stop(){
stopped = true;
th.interrupt(); // 깨워야 바로 반영됨 (응답성이 좋아짐)
}
}
yield()
도 반드시 동작한다는 보장은 없다.