- [Java 기본]Thread, synchronized, 압축 및 배포

Posted by 겨울에
2011. 5. 14. 16:29 scrap/ Java/JSP
출처 :

//===========================================================================//
  본 내용은 2002년 제가 Java 강의를 수강하며 정리 했던 내용을
    기본으로 하여 정리하였습니다.
  - 마침 java 기초를 전파할 기회가 생겨 핑계김에 정리해 가려 합니다.
  작성자 : litwave
//---------------------------------------------------------------------------//

<목차>

1. 압축 및 배포

3. Thread

//---------------------------------------------------------------------------//


1. 압축 및 배포
    1) 압축 : jar -cvf 파일명.jar 압축시킨 파일들
       해제 : jar -xvf 파일명.jar
    2) doc 파일 생성
      -> javadoc 해당파일.java
    3) 배포
      - 배치파일 만들기 : set path = ~
                          set classpath = ~
                          java 실행 클래스
      - readme.txt

2. 압축 및 배포 실습
    2.1 배포파일 만들기
        1) 배포할 파일(소스파일 제외)을 하나의 폴더에 모아 놓는다.
        2) 배포할 파일의 도움말을 만든다.
            /**              */             사이에 도움말 내용을 적는다.
            - 특정 메소드나 클래스 위에 /** 메소드 정보    */ 과 같이 적는다.
        3) 도움말 폴더를 만들어서 java파일들을 복사한다.
            도움말 폴더에서
                javadoc 파일명.java 
            를 하면 해당 도움말 파일이 Html 파일로 생성된다.
        4) 여기서 del *.java를 해서 java 파일을 지워 준다.

    2.2 실행 파일 만들기
        - 자동으로 실행 될 수 있는 배치파일을 만들어야 한다.
        1) 메모장을 열어서(파일명.bat)을 만들고 아래와 같이 입력한다.
            set path = %path%; c:\java\jdk1.4\bin
            set classpath = classpath%;.
            java 파일명

    2.3 압축을 한다.(-cvf : 생성하면서 파일의 이름을 보여 주겠다. 파일명.jar로 모든 파일이 압축 된다.)
        jar -cvf 파일명.jar *.*

    2.4 압축 파일을 제외하고 모두 지워 준다.
    2.5 압축 파일을 배포할 수 있는 .html 파일을 만든다.
     <a href="파일명.jar"> <h2>가져가세요.. </h2> </a>

    2.6 실행
        1) 파일을 받아 온다.
        2) 압축을 푼다
            jar -xvf 파일명.jar
         - Meta-inf폴더에는 압축 정보가 들어있다.

3. Thread
    - Multi Tasking(다중작업)을 자바에서는 Multi Thread라고 이야기 한다.
    - 지금부터 배울 내용은 하나의 프로세스에서 여러개의 다중 작업을 할 수 있는 것을 배울 것이다.
    - 지금까지는 단일 작업을 수행하는 프로그램을 작성하였다.
    - 하나의 시작에서 하나의 끝으로 가는 것을 Thread 라고 하며, 특히 main에서 시작해서 끝나는 것을 main Thread 라 한다.
    - cpu는 기본적으로 한번에 하나의 job을 수행하게 되고, 여러개의 작업이 Thread에 의해서 동시에 발생하면, cpu 쟁탈전이 벌어지게 된다.
    - 과도한 Thread의 사용은 CPU의 과부하를 발생 시키고 속도 저하를 가져올 수 있다.
    - 멀티 쓰레드는 각각이 단독적인 흐름을 가진다.
    - 쓰레드가 언제 실행 될지는 프로그래머는 알 수가 없다.

  3.1 Thread를 만드는 법
    1Thread 클래스를 상속 받는 방법.(java.lang 에 포함되어 잇음)
      class A extends Thread {
        public void run() {  //Thread를 실행하라고 하면.. 이 메소드 부터 실행이 된다.

        }
      }         //A라는 클래스가 하나의 Thread가 된다.
  
      .
      .
      .
      A ap = new A()
      // ap.run();      //하면 단순히 메소드의 실행만 될 뿐이다. 그래서.. 호출하지 않는다.
      ap.start();       //하면 새로운 작업 흐름을 만들고 그것을 실행 시키라고 알려 주는것이다.
                        //start()는 Thread 객체에 포함된 메소드 이다.


    2Runnable 인터페이스를 상속 받는 방법.
      class A implements Runnable {
        public void run() {    //Runnable 에는 이것 하나의 메소드 밖에 없다.


        }
      }

      A ap = new A();
      Thread tt = new Thread(ap);         // 바로 실행이 안되므로 Thread에 담아서 실행 시켜야 한다.
      tt.start(); 


  3.2 Thread 만들기.
    ->  Ex0129_01.java

    - sleep() : 1/1000초 단위의 시간 간격을 줄 수 있다. // 예외 처리를 해 주어야 한다.
    - 중요 : 쓰레드는 다른 것에 영향을 주지 않으면서 하나의 독립적인 흐름을 만들어 낼 수 있다. 
    - 지금 까지 배운 것은 동시에 여러개의 작업이 실행 될 수 있다는 것을 알려 준것이다.


  3.3 Thread Object
    3.3.1 Field Summary
      MAX_PRIORITY = 10
      MIN_PRIORITY = 1         => 우선 순위 이다.
      NORM PRIORITY = 5 
          -> 숫자가 클수록 CPU 점유시간이 길어진다.
          -> 일반적인 Thread 우선 순위는 5라는 값을 가지게 된다.
    3.3.2 Construct Summary
      Thread 마다 이름을 줄 수 있다. 주지 않으면 자동으로.. thread1 ~ 과같이 숫자가 자동으로 붙는다.

    3.3.3 Method Summary
        - 과제: Thread관련 메소드 모두 예제 만들어 오기..
      1activeCount()     // 활동 중인 쓰레드의 갯수를 돌려 준다
      2currentThread()   // 여러개의 쓰레드가 동작 중일때 현재 쓰레드의 이름을 뽑아 준다.
      3enumerate(Thread[] tarray)      //현재 움직이고 있는 Thread 들을 배열로 담아 준다.
         getName()           // Thread 이름을 얻어 온다.
         getPriority()       // 현재 Thread 우선 순위를 얻어온다.

      4interrupt()         // 특정 Thread 하나를 중지 시키고자 할때..         //Exception 발생 시킴
         interrupted()       // 현재의 Thread가 중지되었는지 아닌지를 돌려줌
         isinterrupted()     // 특정 Thread가 중지 되었는지 중지 되지 않았는지를 돌려줌

         isAlive() // 특정 Thread 가 살아 있는지 확인

      5)isDaemon()           // 현재 쓰레드가 데몬인지 아닌지 체크
        ap.setDaemon(true)   // 데몬 쓰레드로 만들겠다.
        ap.setDaemon(false)  // 독립 쓰레드로 만들겠다.
        - 데몬 쓰레드는 특정 쓰레드에 종속된 쓰레드를 의미 하며, 
          데몬 쓰레드는 메인 쓰레드가 종료되면 같이 종료된다.

      6join()         //특정 쓰레드를 끝까지 수행할때 사용한다.
         join(100);   // 0.1초 동안 지연 시켜 준다.(특정 시간동안만 지연 시킬 수 있다.)

         setPriority()   //우선 순위를 주는 것.
                         //start 하기 전에.. 미리 지정을 해 주어야 한다.
         ap.setPriority(Thread.NORM_PRIORITY+2//형태로 적는 것이 정석
         start()      //run() 을 불러주는 메소드
         yield()      //현재 실행 중인 Thread가 다음 Thread 에게 양보를 해준다.

      7wait()     //특정한 시간을 지정해서 특정시간 동안 대기 시키는 메소드
                    //무한정 대기 상태가 될 수도 있다.
         notify()   //wait 된 Thread를 깨우는 메소드..
         notifyAll()   //Thread와 관련되 모든 것을 깨우는 것.. 

//---------------------------------------------------------------------------//
// 수업 관련 소스
// Ex0129_01.java : Thread 구현 예
class Ex0129_01_Sub /*extends Thread*/ 
                     implements Runnable {
    public void run() {
        
        for(int i = 0; i < 20; i++) {
            for(char ch = 'A'; ch <= 'Z'; ch++) {
                if(ch % 10 == 0) {
                    System.out.print(ch + "\n");
                } else{
                    System.out.print(ch + "\t");
                }
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ee) { }
                
            }
        }
    }
}

public class Ex0129_01 {
    public static void main(String[] ar) {
        System.out.println("Main Thread !!");
        System.out.println("Start !!");
        Ex0129_01_Sub es = new Ex0129_01_Sub();
        Thread tt = new Thread(es);
        tt.start();

        for(int i = 1; i <= 500; i++) {
            if(i % 10 == 0){
                System.out.print(i + "\n");
            } else {
                System.out.print(i + "\t");
            }
            try {
                Thread.sleep(50);
            } catch(InterruptedException ee) { }
        }
        System.out.println("\nEnd !!");
    }
}


//---------------------------------------------------------------------------//
// Ex0129_02.java : Runtime 예
public class Ex0129_02 {
    public static void main(String[] ar) {
        Runtime rt = Runtime.getRuntime();
        try {
            rt.exec("explorer.exe http://www.daum.net");
        } catch(java.io.IOException ee) { }
    }
}


//---------------------------------------------------------------------------//
// Ex0129_03.html

<html>

    <head>  
        <title> 시간보기 </title>
    </head>
    <body bgcolor=000000 text=ffffff>
        <center>
            <h2> 이것은 애플릿 </h2><p>
            <applet code="Ex0129_03.class" width=500 height=300>
            <!-- <param name="이름" value="값"> -->
            </applet>
        </center>
        <hr>
        <a href="Ex0129_03.java"> 소스보기 </a>
    </body>
</html>

// Ex0129_03.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Ex0129_03 extends Applet 
                implements RunnableActionListener{
    private Button bt = new Button("Yahoo!");
    private Button bt1 = new Button("Empas!");
    private Button bt2 = new Button("Naver!");
    private Runtime rt;
    public void init(){
        rt = Runtime.getRuntime();
        this.setLayout(new BorderLayout());
        Panel p = new Panel(new FlowLayout());
        p.add(bt);
        p.add(bt1);
        p.add(bt2);
        this.add("South", p);
    }
    public void start(){
        Thread tt = new Thread(this);
        tt.start();
        bt.addActionListener(this);
        bt1.addActionListener(this);
        bt2.addActionListener(this);
    }
    public void run(){
        while(true){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ee){}
            this.repaint();
        }
    }
    public void actionPerformed(ActionEvent e){
        if(e.getSource() == bt){
            try{
                rt.exec("explorer.exe http://www.yahoo.co.kr");
            }catch(Exception ee){}
        }
        else if(e.getSource() == bt1){
            try{
                rt.exec("explorer.exe http://www.empas.com");
            }catch(Exception ee){}
        }
        else if(e.getSource() == bt2){
            try{
                rt.exec("explorer.exe http://www.naver.com");
            }catch(Exception ee){}
        }
    }
    public void paint(Graphics g){
        Calendar ca = Calendar.getInstance();
        String str = ca.get(Calendar.YEAR+ "년 " + 
                (ca.get(Calendar.MONTH+ 1+ "월 " +
                ca.get(Calendar.DAY_OF_MONTH+ "일 " +
                ca.get(Calendar.HOUR_OF_DAY+ "시 " + 
                ca.get(Calendar.MINUTE+ "분 " + 
                ca.get(Calendar.SECOND+ "초";
        g.setFont(new Font("TimesRoman"Font.BOLD20));
        g.drawString("Time : " + str, 50100);
    }
    public static void main(String[] ar){
        Ex0129_03 es = new Ex0129_03();
        es.init();
        es.start();
        Frame f = new Frame();
        f.setLayout(new BorderLayout());
        f.add("Center", es);
        f.setSize(500300);
        f.setVisible(true);
    }
}

//===========================================================================//




--------------------------------------------------------------------------------------------------

>>>>> 답글
 
위의 것 쓰레드부분은 정말 맛배기만인데, 정확히는 스테이트 프로세스 아키텍쳐 
(스테이트 머신)에 대한 개념을 깔고서 각 메소드들의 역할이 상태를 전이하는 역할을 하는 
것이다라는 식으로 설명해주는게 더 좋을 듯 한데.. 

그러면 초급 수준을 뛰어넘게 되니 힘드려낭 -_-;; 

아무튼 가장 개념적인 이해와 설명이 많이 요구되는 부분이 아닐까;; 
동기화문제에 따른 트랜잭션이란 개념도 있궁.. ㅋ 

지금 생각해보면 상당히 날림으로 넘어간 부분중 하나이긴 하는.. ㅎㅎ 

예제도 단순히 쓰레드를 통해서 멀티로 프로세스가 진행 될 수 있다 정도만 보여줄뿐 
쓰레드의 생명주기라던지 등등은 잘 파악하기 힘든 예제라.. 많이 아쉽삼.. ㅋㅋ


-------------------------------------------------------------------------------------------

Thread 동기화 관련된거는 다음 강의 내용에 있더라구.. 일단 거기서 약간 언급될꺼 같고..
나도 기본적인 것만 사용하고 따로 공부를 해본건 아니라.. 깊이 있는 내용은 못다루겠네.. ㅋㅋ...
그럼 관심 가져줘서 고마우이~~ ㅎㅎ.. 
괜찮은 자료 있음 좀 답글로 좀 올려도 좋을듯.. 나도 참고좀 하게..






 



>>>>>> synchronized, Thread 샘플 예제

//===========================================================================//
  본 내용은 2002년 제가 Java 강의를 수강하며 정리 했던 내용을
    기본으로 하여 정리하였습니다.
  - 마침 java 기초를 전파할 기회가 생겨 핑계김에 정리해 가려 합니다.
  작성자 : litwave
//---------------------------------------------------------------------------//

<목차>
1. Synchronize(동기화) 개념
2. 
synchronized
3. Thread 실습

//---------------------------------------------------------------------------//

1. Synchronize(동기화) 개념
  - 하나의 
Thread 에서 무한적으로 수행되는 두개의 Method 를 포함하고 있다고 가정하자.

class A extends Thread {
  
static int x;
  
run() {
    aaa();
    bbb();
  }
  aaa() {
      
// x에 어떤 값을 계속 더하고 출력하는 프로그램  
  }
  bbb() {
      
// x에 또 다른 값을 더하고 출력하는 프로그램 
  }
}

  - 특정한 경우에 aaa()가 모두 처리되고 bbb()를 순차적으로 처리하면 값 x에 동시에 접근하는 문제를 막을 수 있다.
  - 그러므로 하나의 프로그램이 실행이 끝날때 까지 다른 프로그램의 접근을 막는 방법을 생각해 놨다.

  - 
synchronized 는        // 특정 Method 혹은 변수에 lock 를 거는 것이다.
  - 다중 Thread 를 사용할 경우 dead lock이 발생할 수 있으므로, 이러한 상태가 발생하지 않도록 미연에 막아 주어야 한다.
  - dead lock : 서로의 프로그램 간에 상대가 끝나기를 기다리면서 대기 상태로 빠지는 것이다.

2. 
synchronized
  1) 형식 
    접근자 
synchronized 지정어 void aaa(---) { }
     - 특정 Method 에 대해서 접근을 막아줌

  2) 특정 구간에만 lock을 걸 때 사용.(특정 구역의 작업을 할 때는 다른 것의 방해를 받지 않도록 하는 것)

  3) x 라는 변수에만 lock을 걸기 : x라는 변수에 대해서는 어느 누구도 그 구간에서는 아무도 접근 할 수 없게 해준다

    
void aaa() {
       .
       .
      
synchronized(x) {
        x += ?;
      
      }
       .
       .
    }

3. 
Thread 실습 
  - 말달리기 프로그램 만들기

  3.1 말 한마리 셋팅하기..
    1) 
Canvas 상속을 받는 클래스 하나를 만든다.(말이 그려진 판)
    2) 중앙에 가로선을 하나 그린다.
    3) 말을 원으로 그린다.

  3.2 말을 쓰레드로 움직이게 만든다.
    1) 
run() 메소드 정의하기
    2) 말이 움직이는 x좌표를 바꾸고 repaint시킨다.
    3) 출발이라는 버튼을 눌렀을 때 run이 실행 될 수 있도록 고친다.

  3.3 말의 수를 입력 받고 필요 없는 것을 지워 준다.
    1) num과 
set 버튼에 ActionListener 를 추가한다.
    2) 말의 수만 큼.. Center을 분할 시킨다.(Penel을 통해서)
      
this.remove(dist);    // 구성된 화면 지우기..
      this.validate(); // 화면을 재 구성해주는 메소드..

  3.4 말이 셋팅 된 상태에서 출발 버튼을 누르면 말들이 달려가게 만들기
    1) 
start 이벤트에 추가
    2) 
Thread 배열 형태로 말의 수만큼 만든다.
    3) 각 
Thread 에 난수로 우선순위를 주어 출발 시킨다.

  3.5 List창에 도착 순서 뿌리기
    1) 1번말 부터 말의 이름을 지정해 준다.

//---------------------------------------------------------------------------//
// Ex0130_01.html
<html>
    <head><title>말달리기</title></head>
    <body bgcolor='fcfcfc'>
      <center>
        <applet code="Ex0130_01.class" width='700height='600'></applet>
        <hr>
        <font size=10>
          <a href="Ex0130_01.java"> 소스보기 </a>
        </font>
        </center>
    </body>
</html>

// Ex0130_01.java
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

class Ex0130_01_Sub extends Canvas implements Runnable {
    
private int xx;
    
private static int rank = 1;
    
private int hnum;
    
private Ex0130_01 es;
    
public Ex0130_01_Sub(int hnum, Ex0130_01 es) {
        
this.hnum = hnum;
        
this.es = es;
    }
    
public static void setRank(int i) {
        rank = i;
    }
    
public void run() {
        
for(xx=0; xx <= (int)(this.getSize().getWidth() - 10); xx += (int)(Math.random() * 6) + 1) {
            
repaint();
            
try {
              
Thread.sleep(100);
            } 
catch(InterruptedException ee) { }
        }
        xx = (
int)(this.getSize().getWidth()) - 10;
        
repaint();
        es.getRankList().
add(hnum + "번째 말이 " + rank++ + "등으로 도착 했습니다...");
    }
    
public void paint(Graphics g) {
        g.
setColor(Color.black);
        g.
drawLine(0,
            (
int)(this.getSize().getHeight()/2),
            (
int)(this.getSize().getWidth()),
            (
int)(this.getSize().getHeight()/2));
        g.
setColor(Color.red);
        g.
fillOval(xx, 0, 10, (int)(this.getSize().getHeight()));
    }
}

// 
public class Ex0130_01 extends Applet implements ActionListener{
    
//Nor
    //Nor-Flow
    private Label lb1 = new Label("말의 수 : ");
    
private TextField num = new TextField("",4);
    
private Button set = new Button("Set");
    
private Button clear = new Button("Clear");
    
//Center

    //South
    //Sou-Nor
    private Label lb2 = new Label("등 수 판");
    
//Sou-Cen
    private List ranklist = new List(7);
    
//Sou-Sou-Flow
    private Button start = new Button("출발");
    
private Button end = new Button("종료");
    
private boolean frame = false;

    
private Ex0130_01_Sub ess[];
    
public Panel dist = null;
        
    
public Ex0130_01() { }
    
public Ex0130_01(boolean bb) {
        frame = bb;
    }
    
public List getRankList() {
        
return ranklist;
    }
    
    
public void init() {
        
this.setLayout(new BorderLayout());
        lb1.
setForeground(Color.white);
        lb1.
setFont(new Font("둗움"Font.BOLD, 12));
        
Panel p1 = new Panel(new FlowLayout(FlowLayout.CENTER));
        p1.
add(lb1);  p1.add(num);  p1.add(set);  p1.add(clear);
        
this.add("North", p1);
        
//this.add("Center", ess);
        Panel p2 = new Panel(new BorderLayout());
        lb2.
setForeground(Color.white);
        lb2.
setBackground(new Color(192,129,255));
        lb2.
setFont(new Font("둗움"Font.BOLD, 12));
        p2.
add("North", lb2);
        p2.
add("Center", ranklist);
        
Panel p3 = new Panel(new FlowLayout(FlowLayout.RIGHT));
        p3.
add(start);
        
if(frame) {
            p3.
add(end);
        }
        p2.
add("South", p3);
        
this.add("South", p2);
        p1.
setBackground(new Color(192,129,255));
        p3.
setBackground(new Color(192,129,255));
    }
    
public void start() {
        end.
addActionListener(this);
        
start.addActionListener(this);
        num.
addActionListener(this);
        
set.addActionListener(this);
        clear.
addActionListener(this);
    }
    
public void actionPerformed(ActionEvent e) {
        
if(e.getSource() == end) {
            
System.exit(1);

        } 
else if(e.getSource() == start) {
            
Thread[] tt = new Thread[ess.length];
            
for(int i=0; i < tt.length; i++) {
                tt[i] = 
new Thread(ess[i]);
            }
            
for(int i=0; i < tt.length; i++) {
                tt[i].
setPriority((int)(Math.random() * 10) + 1);
            }
            
for(int i=0; i < tt.length; i++) {
                tt[i].
start();
            }
        } 
else if(e.getSource() == num || e.getSource() == set) {
            
int imsi = Integer.parseInt(num.getText().trim());
            dist = 
new Panel();
            dist.
setLayout(new GridLayout(imsi, 1, 5, 5));
            ess = 
new Ex0130_01_Sub[imsi];
            
for(int i=0; i < ess.length; i++) {
                ess[i] = 
new Ex0130_01_Sub(i+1, this);
                dist.
add(ess[i]);
            }
            
this.add("Center", dist);
            
this.validate();
            num.
setEnabled(false);
            
set.setEnabled(false);
            clear.
setEnabled(true);

        } 
else if(e.getSource() == clear) {
            
this.remove(dist);
            
this.validate();
            num.
setText("");
            num.
setEnabled(true);
            
set.setEnabled(true);
            clear.
setEnabled(false);    
            num.
requestFocus();
            Ex0130_01_Sub.setRank(1);
        }
    }
    
    
public void paint(Graphics g) {}
  
    
public static void main(String [] ar) {
        Ex0130_01 h1 = 
new Ex0130_01(true);
        h1.
init();
        h1.
start();
        
Frame f = new Frame("말달리기");
        f.
setLayout(new BorderLayout());
        f.
add("Center", h1);
        f.
setSize(700,600);
        f.
setLocation(200,100);
        f.
setVisible(true);
        f.
addWindowListener(new WindowAdapter() { 
            
public void windowClosing(WindowEvent e) {
                
System.exit(1);
            }
        });
    }
}

//===========================================================================//
 

'scrap >  Java/JSP' 카테고리의 다른 글

- [Java 기본]Swing  (0) 2011.05.14
- [Java 기본] JAVA File I/O  (0) 2011.05.14
- [Java 기본] Applet  (0) 2011.05.14
- [Java 기본] Graphics  (0) 2011.05.14
- [Java 기본]AWT, Listener, Event  (0) 2011.05.14