수요일, 8월 5
Shadow

#066 쓰레드(Thread)

– Application을 구성하는 기능 하나가 하나의 쓰레드
– Java에서는 Method를 하나의 쓰레드로 취급
– 기본적으로 Single Thread ->메서드 하나씩 순차적으로 실행
– 두개이상의 Method를 동시에 실행 Multi Thread

1.Thread클래스를 상속
class ThreadTest extends Thread{
public void run(){/*내용*/} //Thread클래스의 run()을 오버라이딩
}

2.Runnable 인터페이스를 구현
class ThreadTest implements Runnable{
public void run(){/*내용*/} //Runnable인터페이스의 추상메서드 run()을 구현
}

멀티쓰레드 프로그래밍

1. java.lang.Thread를 상속받음
2. public void run()에 멀티쓰레드로 실행할 내용구현
3. Thread의 start()호출 -> 멀티쓰레드로 2개이상의 메서드가 동시에 실행
-> 멀티쓰레드의 스케쥴은 렌덤

 

1. java.lang.Runnable 인터페이스를 상속
2. public void run()에 멀티쓰레드로 실행할 내용구현
3. Thread 생성자의 인자로 Runnable 인터페이스를 구현할 객체의 Reference Variable

t.start ->target 속성이 null이 아니면 targer이 가르키는 객체의 run()을 멀티쓰레드로 실행

Thread상속

접기

public class ThreadTest1 {
public static void main(String[] args) {
GoTest1 goTest1 = new GoTest1();
ComeTest1 comeTest1 = new ComeTest1();

goTest1.start();
comeTest1.start();
}
}


public class GoTest1 extends Thread{
private int i;
public void run(){
while(i<100){
System.out.printf(“go:%d\n”,i++);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


public class ComeTest1 extends Thread{
private int j;
public void run(){
while(j<100){
System.out.printf(“come:%d\n”,j++);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

접기

Runnable상속

접기

public class ThreadTest2 {
public static void main(String[] args) {
GoTest2 goTest2 = new GoTest2();
ComeTest2 comeTest2 = new ComeTest2();
Thread t1 = new Thread(goTest2);
Thread t2 = new Thread(comeTest2);
t1.start();
t2.start();
}
}


public class GoTest2 implements Runnable{
private int i;
public void run(){
while(i<100){
System.out.printf(“go:%d\n”,i++);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


public class ComeTest2 implements Runnable{
private int j;
public void run(){
while(j<100){
System.out.printf(“come:%d\n”,j++);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

접기

쓰레드의 동기화
synchronized를 이용한 동기화

– 하나의 메서드의 공유객체에 대해서 쓰레드가 작업하는 동안 다른 쓰레드는 대기
– 동기화  시킨 메서드를 호출 ->한쓰레드에서 메서드를 포함 객체의 Monitor획득 ->메서드 끝나면 Monitor반납
– 객체 단위의 동기화
– 메서드 단위의 동기화

1. 객체 단위의 동기화
synchronized(객체의 참조변수){
//동기화 시킨후 작업 할일
}
->객체의 참조변수가 가르키는 Monitor 획득
① 1번 쓰레드가 Monitor획득
② 2번 쓰레드가 동기화된 객체에 접근 불가
③ 1번 쓰레드가 Monitor 반납할때까지 2번쓰레드는 대기
④ 1번 쓰레드가 반납하면 2번쓰레드가 접근
2.메서드 단위의 동기화
public synchronized void a(){
//동기화 시킨후 작업 할일
}
① 메서드 호출하는 순간 Monitor 획득
② 종료되면 Monitor 반납

객체 단위의 동기화

접기

public class ThreadTest3 {
public static void main(String[] args) {
MyArray myArray = new MyArray();

PushThread1 push1 = new PushThread1(myArray);
PushThread2 push2 = new PushThread2(myArray);

push1.start();
push2.start();
}
}


public class PushThread1 extends Thread{
private MyArray myArray;

public PushThread1(MyArray myArray){
this.myArray = myArray;
}

public void run(){

while(true){
synchronized(myArray){//myArray가 가르키는 객체의 Monitor획득
if(myArray.index >= myArray.array.length){
break;
}
myArray.array[myArray.index] = myArray.num;
System.out.printf(“PushThread1:myArray.array[%d]=%d\n”,myArray.index,myArray.array[myArray.index]);
myArray.index++;
myArray.num++;

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//end catch
}//myArray가 가르키는 객체의 Monitor반납
}//end while
}//end run
}//end class


public class PushThread2 extends Thread{
private MyArray myArray;

public PushThread2(MyArray myArray){
this.myArray = myArray;
}

public void run(){

while(true){
synchronized(myArray){//myArray가 가르키는 객체의 Monitor획득
if(myArray.index >= myArray.array.length){
break;
}
myArray.array[myArray.index] = myArray.num;
System.out.printf(“PushThread2:myArray.array[%d]=%d\n”,myArray.index,myArray.array[myArray.index] );
myArray.index++;
myArray.num++;

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//end catch
}//myArray가 가르키는 객체의 Monitor반납
}//end while
}//end run
}//end class


public class MyArray {

int []array = new int[20];
int index;
int num;
}

접기

메서드 단위의 동기화

접기

public class ThreadTest3 {
public static void main(String[] args) {
MyArray myArray = new MyArray();

PushThread1 push1 = new PushThread1(myArray);
PushThread2 push2 = new PushThread2(myArray);

push1.start();
push2.start();
}
}


public class MyArray {

private int []array = new int[20];
private int index;
private int num;

public synchronized boolean push(String threadName){
if(index>=array.length){
return false;
}
array[index]=num;
System.out.printf(“%s:array[%d]=%d\n”,threadName,index,array[index]);
index++;
num++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}


public class PushThread1 extends Thread{
private MyArray myArray;

public PushThread1(MyArray myArray){
this.myArray = myArray;
}

public void run(){

while(true){
if(!myArray.push(“PushThread1”)){
break;
}

}//end while
System.out.println(“run()메스드가 끝나면 PushThread1이 종료합니다”);
}//end run
}//end class


public class PushThread2 extends Thread{
private MyArray myArray;

public PushThread2(MyArray myArray){
this.myArray = myArray;
}

public void run(){

while(true){

if(!myArray.push(“PushThread2”)){
break;
}

}//end while
System.out.println(“run()메스드가 끝나면 PushThread2이 종료합니다”);
}//end run
}//end class

접기

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다