'Java/Working-level Java'에 해당되는 글 11건

  1. 2015.01.26 InputStream
  2. 2015.01.26 OutputStream
  3. 2015.01.26 Stream
  4. 2015.01.22 FileWriter : FIndAll
  5. 2015.01.14 Thread 3
  6. 2015.01.14 Thread 2
  7. 2015.01.06 Thread
  8. 2015.01.06 System
  9. 2015.01.03 StringBuffer / StringBuilder
  10. 2014.12.26 ChatClient
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

InputStream은 모든 입력 스트림 서브 클래스들의 슈퍼 클래스이다.



InputStream 메소드들


int available()

read() 메소드를 호출하였을 때 호출한 스레드의 블록 없이 현재 입력 스트립에서 읽어들일 수 있는 바이트의 수를 반환한다.(또는 skip() 메소드가 호출되었을 때 건너뛸 수 있는 바이트 수), 이 메소드는 I/O 에러가 발생하면 IOException을 던진다. 이 메소드를 오버라이드한 서브 클래스에서 스트림의 전체 크기를 반환하지 않을 수도 있으므로 이 메소드의 반환값으로 스트림의 모든 데이터를 저장하는 버퍼를 할당해서는 안된다.


void close()

현재 입력 스트림을 닫고 스트림과 연관되어 있는 시스템 리소스를 해제한다. 이 메소드는 I/O 에러가 발생하면 IOException을 던진다(InputStream에서 Closeable을 구현하기 떄문에 입력 스트림과 함께 try-with-resources 문을 사용할 수 있다)


void mark (int readlimit)

입력 스트림의 현재 위치를 마크(mark)한다. reset() 메소드가 호출되면 마지막에 마크된 위치로 현재 위치가 옮겨지며 이후에 읽기 작업을 수행하면 옮겨진 위치부터 바이트를 읽어들인다. readlimit 인자는 현재 지정한 마크가 무효화되기 전에 읽어들일 바이트의 수가 지정되며 입력 스트림에 통지된다. 지정한 바이트의 개수를 다 읽어들이기 전에 스트림은 마크된 위치를 재설정할 수 없다.


boolean markSupported()

현재 입력 스트림이 mark()와 reset() 메소드를 지원하면 true를 반환하고 아니면 false를 반환한다.


int read()

현재 입력 스트림에서 한 바이트를 읽어 반환한다. 반환되는 값은 0-255 사이이며 스트림의 마지막에서 읽기를 시도하면 -1이 반환된다. 이 메소드는 I/O 에러가 발생 할 경우 IOException을 던진다.


int read(byte[] b)

현재 입력 스트림으로 부터 바이트들을 읽어 배열 인자 b에 저장한다. 반환되는 값은 실제 읽어들인 바이트의 수이다. 만일 스트림의 마지막에 도달했을 경우에는 -1을 반환한다. 읽어들인 바이트 수는 b의 길이보다 작거나 같다. 이 메소드는 인자 b가 null일 떄 NullPointerException 그리고 I/O에러가 발생하면 IOException을 던진다.


int read(byte[] b, int off, int len)

현재 입력 스트림에서 인자 off에 지정한 오프셋 위치에서부터 인자 len로 지정한 값보다 같거나 작은 개수의 바이트를 읽어 인자 배열 b에 저장한다. 실제로 읽어들인 바이트의 개수를 반환하거나 스트림의 끝이면 -1을 반환한다.

이 메소드는 인자 b가 null 이면 NullPointerException을, 인자off 또는 len이 음수이거나 len이 b.length - off 보다 큰 수로 지정이 되면 IndexOutOfBoundsException을 그리고 I/O 에러가 발생하면 IOException을 던진다.


void reset()

마지막으로 mark() 메소드가 호출된 곳으로 위치를 재설정한다. 입력 스트림에 마크된 적이 없거나 마크가 무효화되었을 경우 IOException을 던진다.


long skip(long n)

인자 n에 지정한 바이트 수만큼 입력 스트림을 건너 뛴다. n에 지정한 바이트 수보다 남은 입력 스트림 데이터가 적으면 입력 스트림의 마지막으로 건너뛴다. 실제 건너뛴 바이트의 개수가 반환된다. 인자 n이 음수로 지정이 되면 위치를 이동하지 않는다. 이 메소드는 입력 스트림이 건너띄기를 지원하지 않거나 I/O 에러가 발생하면 IOException을 던진다.



ByteArrayInputStream()과 같은 InputStream()의 서브 클래스들은 mark() 메소드를 통해 현재 읽기 위치를 스트림에 지정할 수 있으며 reset() 메소드를 호출에 마크했던 위치로 돌아가는 기능을 제공한다.


***

현재 사용하고 있는 스트림 서브 클래스가 mark()와 reset() 메소드를 지원하는지 알기 위해서는 markSupported() 메소드를 호출해야 한다는 것을 명심하자






'Java > Working-level Java' 카테고리의 다른 글

OutputStream  (0) 2015.01.26
Stream  (0) 2015.01.26
FileWriter : FIndAll  (0) 2015.01.22
Thread 3  (0) 2015.01.14
Thread 2  (0) 2015.01.14
Posted by af334
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

자바에서는 I/O스트림을 수행하는 OutputStream 과 InputStream 클래스를 제공한다. OutputStream은 모든 출력 스트림 서브 클래스의 슈퍼 클래스다.



OutputStream 메소드들


void close()

현재 출력 스트림을 닫고, 스트림과 연관되어 있는 리소스를 해제한다. I/O 에러가 발생하면 IOException을 던진다(OutputStream에서 Closeable을 구현하고 있기 때문에 출력 스트림과 함께 try-with-resources 문을 사용할 수 있다)


void flush()

현재 출력 스트림에 있는 바이트들을 플러쉬한다. 만일 최종 목적지가 파일과 같이 하위 플랫폼에 의해 제공되는 추상적인 디바이스이면 플러쉬를 하더라도 오직 하위 플랫폼의 추상 디바이스까지만 바이트들이 전달되고 하위 플랫폼이 제어하는 물리적인 디바이스(예를 들어 하드디스크) 까지 완전히 전해진다고 보증할 수는 없다.이 메소드는 I/O에러가 발생하면 IOException을 던진다.


void write(byte[] b)

byte 배열 인자 b의 내용을 출력 스트림으로 보낸다. 보내지는 바이트의 수는 b.length가 된다. 이 메소드는 b가 null일 경우 NullPointerException을, I/O에러가 발생하면 IOException을 던진다.


void write(byte[] b, int off, int len)

인자 off로 지정한 위치에서부터 인자 len에 지정한 개수만큼 인자 b의 byte 배열에서 바이트를 읽어 현재 출력 스트림으로 보낸다. 인자 b의 값이 null이면 NullPointerException을, 인자 off의 값이 음수이거나 값이 b.length보다 크면 java.lang.IndexOutOfBoundsException을 그리고 I/O 에러가 발생하면 IOException을 던진다


void write(int b)

바이트 인자 b를 출력 스트림으로 보낸다. b가 int 타입이기 때문에 하위 8비트만 전달되고 상위 24비트는 무시된다.




flush() 메소드는 애플리케이션 실행 도중 특정 간격으로 데이터를 수시로 저장을 해야하는 텍스트 에디터 같은 애플리케이션에 유용하게 쓰인다. 이 메소드는 바이트들을 물리적인 디스크가 아닌, 바로 아래의 하위 플랫폼까지만 전달한다는 것을 명심하자


***

close() 메소드는 자동적으로 출력 스트림을 플러쉬한다. 그러므로 애플리케이션이 종료되기 전에 close()를 호출하면 출력 스트림을 닫고 스트림에 있는 데이터를 자동적으로 플러쉬한다.

















'Java > Working-level Java' 카테고리의 다른 글

InputStream  (0) 2015.01.26
Stream  (0) 2015.01.26
FileWriter : FIndAll  (0) 2015.01.22
Thread 3  (0) 2015.01.14
Thread 2  (0) 2015.01.14
Posted by af334
2015. 1. 26. 15:33
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

File그리고 RandomAccessFile 클래스와 더불어 자바에서는 I/O 작업을 수행하기 위해 스트림(Stream)을 사용한다. 스트림은 임의의 길이를 가진 바이트들이 정렬되어 있는 시퀸스이다. 애플리케이션에서 바이트들을 파일 또는 화면과 같은 목적지로 전달할 때는 출력 스트림을 통해 전달되며 파일같은 소스에서 바이트들이 애플리케이션으로 전달될 때는 입력 스트림을 통해 전달이 된다.


application   ----write ---->   destination

output stream


source    ---read----> application

input stream



자바에서는 바이트 배열, 파일, 스크린 그리고 소켓과 같은 다양한 목적지를 사용할 수 있으며 바이트 배열, 파일, 키보드 그리고 소켓과 같은 다양한 소스를 사용할 수 있다.




스트림(Stream) 클래스 개요

java.io 패키지는 OutputStream 과 InputStream 추상 클래스의 후손인 몆가지  출력 스트림과 입력 스트림 클래스를 제공한다.



출력 스트림의 계층구조

OutputStream (abstruct)

ByteArrayOutputStream

FileOutputStream

FilterOutputStream

BufferedOutputStream

DataOutputStream

ObjectOutputStream

PipedOutputStream




입력 스트림 클래스 구조

InputStream (abstruct)

ByteArrayInputStream

FileInputStream

FilterInputStream

BufferedInputStream

DataInputStream

LineNumberInputStream

PushbackInputStream

ObjectInputStream

PipedInputStream

SequenceInputStream

StringBufferInputStream


LineNumberInputStream와 StringBufferInputStream은 문자 인코딩을 지원하지 않기 때문에 사용이 금지되었다. 이 사용 금지된 메소들 대신 LineNumberReader와 StringReader를 사용해야 한다.



***

PrintStream도 다른 언어의 문자 인코딩을 지원하지 않기 때문에 사용해서는 안되며 대신 PrintWriter를 사용해야 한다. 하지만 PrintStream은 System클래스의 out 과 err 클래스 필드 타입으로 너무나 광범위하게 사용되었기 때문에 사용 금지가 되지는 않았다.



java.io 패키지가 아닌 다른 자바 패키지에서도 몇가지 입/출력 스트림 클래스를 제공한다. 예를 들어 java.util.zip 패키지에서는 압축되지 않은 데이터를 압출하는 다섯 가지 출력 스트림 클래스를 제공하며 압축된 데이터를 압축 해제를 하는 다섯가지 입력 스트림을 제공한다.


CheckedOutputStream            

CheckedInputStream


DeflaterOutputStream           

DeflaterInputStream


GZIPOutputStream

GZIPInputStream


InflaterOutputStream

InflaterInputStream


ZipOutputStream

ZipInputStream




'Java > Working-level Java' 카테고리의 다른 글

InputStream  (0) 2015.01.26
OutputStream  (0) 2015.01.26
FileWriter : FIndAll  (0) 2015.01.22
Thread 3  (0) 2015.01.14
Thread 2  (0) 2015.01.14
Posted by af334
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

package FileReader;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class GuiFindAll {
    final static String LINE_SEPARATOR=System.getProperty("line.separator");
    static JTextArea txtSrchResults;
    static JFrame f;
    static volatile String result;
    static JPanel createGUI(){
        JPanel pnl=new JPanel();
        pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
        JPanel pnlTemp=new JPanel();
        JLabel lblStartDir=new JLabel("Start directory");
        pnlTemp.add(lblStartDir);
        final JTextField txtStartDir=new JTextField(30);
        pnlTemp.add(txtStartDir);
        pnl.add(pnlTemp);
        pnlTemp=new JPanel();
        JLabel lblSrchText=new JLabel("Search text");
        pnlTemp.add(lblSrchText);
        lblSrchText.setPreferredSize(lblStartDir.getPreferredSize());
        final JTextField txtSrchText=new JTextField(30);
        pnlTemp.add(txtSrchText);
        pnl.add(pnlTemp);
        pnlTemp=new JPanel();
        JButton btnSearch=new JButton("Search");
        pnlTemp.add(btnSearch);
        pnl.add(pnlTemp);
        pnlTemp=new JPanel();
        txtSrchResults=new JTextArea(20,30);
        pnlTemp.add(new JScrollPane(txtSrchResults));
        pnl.add(pnlTemp);
        ActionListener al;
        al=new ActionListener() {
           
            @Override
            public void actionPerformed(ActionEvent e) {
                final String startDir=txtStartDir.getText();
                final String srchText=txtSrchText.getText();
                txtSrchResults.setText("");
                Runnable r;
                r=new Runnable() {
                   
                    @Override
                    public void run() {
                        if(!findAll(new File(startDir),srchText)){
                            Runnable r=new Runnable() {
                               
                                @Override
                                public void run() {
                                    String msg="not a directory";
                                    JOptionPane.showMessageDialog(f, msg);
                                }
                            };
                            EventQueue.invokeLater(r);
                        }
                    }
                };
                new Thread(r).start();
            }
        };
        btnSearch.addActionListener(al);
        return pnl;
    }

    static boolean findAll(File file, String srchText){
        File[] files=file.listFiles();
        if(files==null)
            return false;
        for(int i=0;i<files.length;i++)
            if(files[i].isDirectory())
                findAll(files[i],srchText);
            else
                if(find(files[i].getPath(),srchText)){
                    result=files[i].getPath();
                    Runnable r=new Runnable() {
                       
                        @Override
                        public void run() {
                            txtSrchResults.append(result+LINE_SEPARATOR);
                        }
                    };
                    EventQueue.invokeLater(r);
                }
            return true;
    }

    static boolean find(String filename, String srchText){
        try(BufferedReader br=new BufferedReader(new FileReader(filename))) {
            int ch;
            outer_loop:
            do{
                if((ch=br.read())==-1)
                    return false;
                if(ch==srchText.charAt(0)){
                    for(int i=1;i<srchText.length();i++){
                        if((ch=br.read())==-1)
                            return false;
                        if(ch!=srchText.charAt(i))
                            continue outer_loop;
                    }
                    return true;
                }
            }
            while(true);
           
        } catch (IOException ioe) {
                System.err.println("I/O error : "+ ioe.getMessage());
        }
        return false;
    }
    public static void main(String[] args){
        Runnable r=new Runnable() {
           
            @Override
            public void run() {
                f=new JFrame("FindAll");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setContentPane(createGUI());
                f.pack();
                f.setResizable(false);
                f.setVisible(true);
            }
        };
        EventQueue.invokeLater(r);
    }
}



=============



FindAll클래스에서는 createGUI(), findAll(), find() 그리고 main() 클래스 메소드와 함께 여러 개의 클래스 필드를 선언하고 있다. FindAll은 멀티 스레드 애플리케이션이다. 메인 스레드는 main()을 실행만 시키고 FindAll의 GUI는 EDT(event-dispatch thread)에서 실행이 되고 findAll()메소드를 실행하는 워커 스레드를 생성한다.


특정 시점에 스레드는 공유된 변수들 (shared variables)과 커뮤니케이션해야 하는데 이런 커뮤니케이션은 동기화 문제를 발생시킬 수 ㅇ씨다. 이런 동기화 문제를 피하기 위해 위의 예제에서는 volatile result 필드를 생성했으며 final 로컬 변수들을 사용한다.


result 필드를 volatile로 선언했기 때문에 멀티코어 또는 멀티 프로세서 플랫폼 상에서도 각각의 코어 또는 프로세서가 이 필드의 복사본을 갖고 있기 때문에 EDT와 워커 스레드에서 result의 String 참도 값을 확인 할 수 있다. 만일 result가 volatile로 선언되어 있지 않으면 EDT에서는 findAll() 메소드에서 일치하는 문자를 찾았을 때 새로운 String 객체가 할당된 result의 참도를 볼 수 없을 것이다( 싱글 프로세서 또는 싱글 코어 플랫폼에서는 이런 문제가 발새하지 않는다)


위와 같은 이유로 startDir와 srchText 로컬 변수를 가지고 있지만 이 로컬 변수들은 volatile이 아닌 final로 선언되어 있다. 이 러컬 변수들은 final로 선언되어 있어야 검색 버튼의 액션 리스너 내의 java.lang.Runnable로 구현된 익명 클래스에서 접근이 가능하다.


결과적으로 final 필드에 대해서는 volatile 선언이 필요하지 않으며 한 필드에 대해 volatile과 final을 동시에 지정을 할 수는 없다. final 필드는 안전하게 접근할 수는 있지만, 반드시 final 참조 필드를 참조하는 객체가 필요하지는 않다. String 객체는 불변이기 때문에 startDir, srchText 그리고 result에서 String 메소드를 호출해도 문제가 발생하지 않는다.


검색 버튼에서 액션 리스너는 runnable내에서 runnable을 선언하고 있어 코드가 복잡해 보이는데 다음은 이 코드들이 어떻게 동작하는지를 단계별로 소개한다.



1. 사용자가 검색 버튼을 누르면 actionPerformed()메소드가 호출된다.


2. actionPerformed() 메소드에서는 검색을 시작할 디렉터리와 검색할 문자를 텍스트 필드에서 가지고 온 후 새로운 검색 결과를 보여주기 위해 텍스트 영역을 " " 로 초기화 한다. 다음, runnable을 생성하고 EDT에서 워커 스레드를 실행한다.


3. 다음, 작업 스레드는 run()메소드 호출을 통해 runnable을 실행할 것이다.


4. run()에서는 검색을 시작하기 위해 findAll()메소드를 호출한다. 만일 finaAll()이 false를 반환하면 javax.swing.JOptionPane 기반의 다이얼로그 박스를 통해 에러 메시지를 출력하는 새로운 runnable이 생성된다. 워커 스레드는 EDT에 다이얼로그 박스에 보여주기 위해 javax.awt.EventQueue의 invokeLater() 메소드를 실행한다.


다음과 같은 코드를 볼 수 있다.


pnl.setLayout (new BoxLayout (pnl, BoxLayout.Y_AXIS));


이 코드는 컨테이너의 컴포넌트를 배치하기 위해 스윙의 javax.swing.BoxLayout 클래스를 사용하는 것이다. java.awt.GridLayout와는 달리 BoxLayout 은 컴포넌트들에게 같은 크기를 지정하지 않는다. 검색 결과가 많이 반환 될 수 있으므로 텍스트 영역은 스크롤이 가능해야 한다. 하지만 이 컴포넌트는 기본적으로 스크롤을 지원하지 않으므로 스크롤을 지원하기 위해 scrollpane을 추가해야 하는데 javax.swing.JScrollPane 클래스를 사용하여스크롤을 지원할 수 있다.


JScrollPane은 스크롤이 추가될 컴포넌트와 함께 호출되는 생성자를 제공하는데 예를 들어 JScrollPane(Component view) 형식의 생성자를 제공한다. 이와는 대조적으로 AWT의 java.awt.ScrollPane 클래스는 add() 메소드를 사용해 스크롤을 지원할 컴포넌트를 전달한다.





정리


많은 애플리케이션에서 파일에 데이터를 저장하거나 파일로부터 데이터를 읽어 오기 위해 파일시스템과 상호 작용을 한다. 자바의 표준 클래스 라이브러리에서는 File, RandomAccessFile, 스트림 그리고 writer/reader API를 통해 파일 시스템에 접근을 제공한다.


자바는 플랫폼 하부의 파일시스템에 접근할 수 있는 FIle 실제 클래스를 제공하는데 File 인스턴스는 파일 또는 디렉터리의 추상 경로명을 포함하고 있다.


파일들은 읽기/쓰기를 같이 사용할 수 있는 임의 접근 형식으로 오픈될 수 있는데 자바에서는 이런 임의 접근(random access)을 RandomAccessFile 클래스를 통해 지원한다.


자바는 I/O 작업을 수행하기 위해 스트림을 사용한다. 스트림은 임의의 길이를 가지는 바이트들의 시퀸스를 의미한다. 바이트들은 애플리케이션으로부터 출력 스트림을 통해 목적지로 전달되며 소스에서 입력 스트림을 통해 애플리케이션으로 전달된다.


java.io 패키지에서는 OutputStream과 InputStream 추상 클래스로부터 파생된 여러가지 출력 스트림과 입력 스트림을 제공한다. FileOutputStream와 BufferedInputStream이외에도 여러가지 스트림 서브 클래스들이 제공된다.


자바의 스트림 클래스는 바이트의 시퀸스를 스트림하기에 적합하지만 바이트 스트림은 문자 셋과 인코딩을 지원하지 못하기 때문에 문자의 시퀸스를 스트림하기에는 부적합하다. 문자에 대한 스트림이 필요하다면 문자 I/O를 지원하도록 설계된 자바의 쓰기와 읽기 클래스들을 사용해야 하는데 이런 클래스들은 문자 인코딩을 지원한다.


java.io 패키지에서 Writer와 Reader 추상 클래스로부터 파생된 여러가지 쓰기와 읽기 클래스를 제공한다. 대표적인 쓰기, 읽기 클래스로는 OutputStreamWriter, FileWriter, InputStreamReader, FileReader 그리고 BufferedReader 등이 있다.


많은 애플리케이션에서 파일시스템뿐만 아니라 네트워크 그리고 데이터베이스와 상호 작용을 한다.













'Java > Working-level Java' 카테고리의 다른 글

OutputStream  (0) 2015.01.26
Stream  (0) 2015.01.26
Thread 3  (0) 2015.01.14
Thread 2  (0) 2015.01.14
Thread  (0) 2015.01.06
Posted by af334
2015. 1. 14. 03:06
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

일반적으로 분리된 스레드가 종료될 때까지 대기하기 위해 while문을 사용하여 반복문 내에서 분리된 스레드의 isAlive() 메소드를 사용해 스레드의 종료 여부를 확인한다. 하지만 join()메소드를 사용해 이런 대기 작업을 대신 할 수 있다.




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



package Thread;

public class JoinDemo {
    public static void main(String[] args){
        Runnable r=new Runnable() {
           
            @Override
            public void run() {
                System.out.println("Worker thread is simulating "+"work by sleeping for 5 seconds.");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ie) {
                }
                System.out.println("Worker thread is dying");
            }
        };
        Thread thd=new Thread(r);
        thd.start();
        System.out.println("Default main thread is doing work");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ie) {
        }
        System.out.println("Default main thread has finished its work");
        System.out.println("Default main therad is waiting for worker thread "+"to die");
       
        try {
            thd.join();
        } catch (InterruptedException ie) {
        }
        System.out.println("Main thread is dying");
    }
}


기본 메인 스레드에서 작업 스레드를 시작한 후 몇가지 작업을 처리하는데 작업 스레드의 thd객체를 통해 호출된 join()메소드에 의해 작업 스레드가 종료될 때까지 대기한다.


모든 Thread 객체는 ThreadGroup 객체에 고한다. Thread 클래스는 ThreadGroup 객체를 반환하는 ThreadGroup getThreadGroup() 메소드를 선언하고 있는데 ThreadGroup 객체는 거의 사용되지 않기 때문에 무시해도 된다. 만일 논리적인 Thread 객체 그룹이 필요하다면 배열 또는 콜렉션을 사용하여 그룹핑하는 것이 더 효율적이다.



***

ThreadGroup 클래스의 몇몇 메소드는 결함이 있다. 예를 들어 int enumerate(Thread[] threads) 메소드는 인자 threads의 배열이 Thread 객체들을 저장하기에 충분한 크기가 아닐 경우 모든 액티브 스레드를 포함하지 못한다. 배열의 정확한 크기를 알기 위해 int activeCount(); 메소드에서 반환하는 값을 사용할 수 있을 거라 생각할 수도 있지만 activeCount() 메소드의 반환값은 스레드의 생성과 종료에 따라 수시로 변동이 되기 때문에 반환된 값이 정확한 배열의 크기가 될 수 없는 경우가 많다.






'Java > Working-level Java' 카테고리의 다른 글

Stream  (0) 2015.01.26
FileWriter : FIndAll  (0) 2015.01.22
Thread 2  (0) 2015.01.14
Thread  (0) 2015.01.06
System  (0) 2015.01.06
Posted by af334
2015. 1. 14. 02:43
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

일반적으로 운영체제에서 스레드들에 대해 각각의 프로세서 또는 코어를 할당하여 스레드를 동시에 실행시킨다. 만일 컴퓨터에 스레드를 실행하기 위한 프로세서 또는 코어에 대한 여유가 없으면 스레드는 공유 프로세서 또는 코어를 사용하기 위해 대기를 한다.


운영체제는 이렇게 대기하고 있는 스레드를 어느 시점에 실행 시킬지를 결정하기 위해 스케쥴러를 사용한다. 스케쥴러는 운영체제에 따라 다른데 다음 리스트는 리눅스와 윈도우에서 사용되는 스케쥴러의 예이다.


***

출력결과가 첫 번째 스레드가 실행되는 것이 먼저 출력이 되었지만 스케쥴러에 따라 출력 순서가 달라 질 수 있다 



다단계 피드백 큐 스케쥴러를 포함한 다른 많은 스레드 스케쥴러에서 스레드 우선 순위 개념을 사용한다. 흔히 스케쥴러들은 선점형 스케쥴링(preemptive scheduling; 높은 우선 순위의 스레드를 먼저 실행)과 라운드 로빈 스케쥴링(round robin scheduling; 우선 순위가 같은 스레드는 시간을 분배하여 분배된 시간동안 번갈아 가면서 스레드를 실행) 이 결합된 형태로 구현되어 있다.


Thread 클래스는 void setPriority(int priority) 메소드와 int getPriority() 메소드를 통해 우선 순위를 지정하거나 우선 순위를 알아낼 수 있다. setPriority(int priority) 메소드는 Thread.MIN_PRIORITY에서 Thread.MAX_PRIORITY 범위에 있는 우선 순위 값을 스레드에 지정할 때 사용되는데, 기본 우선 순위값은 Thread.NORMAL_PRIORITY이다. int getPriority() 메소드는 스레드의 현재 우선 순위값을 반환한다.



***

스케쥴러마다 우선 순위를 조작하는 방법이 다를 수 있기 때문에 setPriority() 메소드를 사용할 경우 자바의 장점 중 하나인 플랫폼 이동성에 영향을 줄 수 있다. 예를 들어 몇몇 플랫폼 스케쥴러의 경우 우선 순위가 높은 스레드가 종료할 때까지 우선 순위가 낮은 스레드는 대기한다. 이런 스케쥴러의 경우 우선 순위가 낮은 스레드가 실행되기 위해 우선 순위가 높은 스레드가 종료할 때까지 많은 시간을 기다려야 하는 경우가 발생하기 때문에 무한 연기(indefinite postponement)또는 스터베이션(starvation)을 일으킬 수 있으며 또한 애플리케이션의 실행 속도를 심각하게 저하시킬 수 있다.




다음 코드는 main()메소드에서 각 스레드의 이름을 지정하고 name과 count를 출력 한 후 스레드를 대기(sleep)한다.



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

package Thread;

public class CountingThreads02 {
    public static void main(String[] args){
        Runnable r=new Runnable() {
           
            @Override
            public void run() {
                String name=Thread.currentThread().getName();
                int count=0;
                while(true){
                    System.out.println(name+": "+count++);
                     try {
                        Thread.sleep(100);
                    } catch (InterruptedException ie) {
                    }
                }
            }
        };
       
        Thread thdA=new Thread(r);
        thdA.setName("A");
        Thread thdB=new Thread(r);
        thdB.setName("B");
        thdA.start();
        thdB.start();
    }
}



Threads A와 B를 100밀리 초동안 대기시키기 위해 Thread.sleep(100); 를 지정하였다. 이렇게 대기하여 각 스레드 실행을 좀 더 주기적으로 할 수 있다.


스레드는 계산이 많은 작업이나 파일 다운로드와 같이 시간이 많이 걸리는 작업을 수행하기 위해 메인 스레드에서 작업을 분리하여 다른 스레드에서 작업을 처리한다. 분리된 작업이 종료된 후 호출한 스레드는 분리된 스레드의 결과 처리를 할 준비를 하며 분리된 스레드가 종료될 때까지 대기한다.










'Java > Working-level Java' 카테고리의 다른 글

FileWriter : FIndAll  (0) 2015.01.22
Thread 3  (0) 2015.01.14
Thread  (0) 2015.01.06
System  (0) 2015.01.06
StringBuffer / StringBuilder  (0) 2015.01.03
Posted by af334
2015. 1. 6. 05:52
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

애플리게이션은 애플리게이션의 코드를 통해 독립적인 실행 경로를 갖는 스레드를 통해 실행된다. 만일 여러개의 스레드가 실행되면 그레드 별로 다른 경로를 가지게 되는데 예를 들어 한 애플리케이션에 여러개의 스레드가 실행될 경우 코드에 switch문이 있을 때 스레드 별로 분리되어 서로 다른 case절이 실행 될 수 있다.


스레드는 애플리케이션의 성능을 높이기 위해 사용한다. 애플리게이션의 목적에 따라 일부 애플리게이션은 주어진 작업을 수행하기 위해 오직 기본 main 스레드만을 사용할 수 있으며, 다른 일부 애플리케이션은 시간이 많이 소요되는 작업을 백그라운드에서 처리하기 위해 추가적인 스레드를 사용하기도 한다.대기 시간이 길어지는 작업을 백그라운드로 스레드로 처리하며 백그라운드 작업의 종료 여부와 상관없이 지속적으로 사용자의 요구에 대응을 할 수 있다.


JVM은 스레드간의 간섭을 방지하기 위해 스레드별로 메소드 호출 스택을 갖고 만든다. 이 분리된 스택들은 스레드의 명령을 수행할 경로를 유지시켜 주며 더불어 이 스택은 메소드 파라미터, 로컬 변수 그리고 반환값의 복사본과 스레드를 제공한다.


자바는 Threading API를 통해 스레드를 지원하는데 이 API는 java.lang.package에 위치하며 하나의 인터페이스(Runnable) 그리고 네개의 클래스 (Thread, ThreadGroup, ThreadLocal, InheritableThreadLocal)로 구성되어 있다.


자바 5에서는 낮은 수준의 Threading API에 대한 대안이 되는 높은 수준의 java.util.concurrent 패키지를 소래한다. 비록 java.util.concurrent가 개발자가 선호하는 API 형태로 스레드와 작업을 제공하지만 간단한 스레딩을 작성할 경우 낮은 수준의 Threading API가 도움이 된다.



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



Runnable과 Thread


자바에서는 인터페이스의 void run() 메소드(인자와 반환값이 없음)를 통해 스레드를 실행시키는 코드를 포함하고 있는 객체를 식별하기 위한 Runnable 인터페이스를 제공한다. 클래스에서는 스레드 코드를 제공하기 위해서 Runnable을 구현하며 이런 클래스 중 하나가 Thread클래스이다.


Thread 클래스는 애플리케이션이 실행되는 운영체제의 스레딩 아키텍처와 일치하는 인터페이스를 제공한다(일반적으로 운영체제에서 스레드의 생성과 관리에 대한 책임을 진다). Thread클래스는 코드와 스레드를 연결하고, 스레드들에 대한 시작과 관리를 하며 각각의 Thread 인스턴스는 각각의 스레드와 연결이 된다.


Thread 클래스에는 Thread 객체를 초기화하는 몆가지 생성자가 선언되어 있는데 일부 생성자는 Runnable을 인자로 받으며 Thread의 확장없이 실행 될 수 있는 코드를 제공 할 수 있다. Runnable로 초기화하지 않고, 대신 Thread의 서브 클래스에서 Thread()를 호출하는 생성자를 제공하여야 하며 서브 클래스에서 Thread의 run() 메소드를 오버라이드 해야 한다.


인자에 명시된 이름이 없기 때문에 각 생성자는 Thread객체에 Thread-로 시작되며 중복이 안되는 기본 이름을 할당한다. 이렇게 동적으로 생성되고 중복이 안되는 이름을 사용해 서로 다른 스레드를 만드를 것이 가능하다. 동적으로 중복이 안되는 기본 이름이 제공되는 위의 두 생성자와는 달리 Thread(String threadName) 생성자에서는 스레드의 이름을 임의로 저장할 수 있다.


Thread 클래스에서는 스레드를 시작하고 관리할 수 있는 메소드를 포함하고 있다




스레드 메소드들


static Thread currentThread()

이 메소드를 호출한 스레드와 연관되어 있는 Thread 객체를 반환한다.


String getName()

현재 Thread 객체의 이름을 반환한다.


Thread.State getState()

현재 Thread 객체와 연관되어 있는 스레드의 상태를 반환한다. 상태는 Thread.State enum형으로 식별이 되며 상태에는 BLOCKED(lock 대기), NEW(생성하지만 시작은 안함), RUNNABLE(실행중), TERMINATED(스레드 종료), TIMED_WAITING(지정한 시간만큼 대기), WAITING(무기한 대기) 등이 있다.


void interrupt()

현재 Thread객체에 인터럽트 상태 플래그를 설정한다. 만일 스레드가 블록 또는 대기 상태가 되면 이 플래그가 클리어되고 InterruptedException 클래스의 인스턴스가 던져져 스레드가 꺠어나게 된다.


static boolean interrupted()

스레드에 보류된 인터럽트 요청이 있을 경우 true를 반환한 후 인터럽트 상태 플러그를 클리어 한다.


boolean isAlive()

현재 Thread 객체와 연관된 스레드가 활동 상태에 있을 때 true를 반환한다. 데몬 스레드는 사용자 스레드를 도와주며 애플리케이션의 마지막 비데몬 스레드가 종료되어 애플리게이션이 종료될 때 자동적으로 종료된다. 현재 Thread객체와 관련되어 있는 스레드가 데몬 스레드 일 때 true를 반환한다. 데몬 스레드는 사용자 스레드에 대한 헬퍼 스레드 역할을 하며 애플리게이션의 마지막 일반 스레드(데몬 스레드가 아닌 스레드) 가 종료될 떄 자동적으로 종료된다.


boolean isInterrupted()

현재 Thread 객체와 연관되어있는 스레드에 보류되어 있는 인터럽트 요청이 있을 때 true를 반환한다.


void join()

현재 Thread 객체에서 이 메소드를 호출한 스레드를 객체와 연관된 스레드가 종료할 때까지 기다린다. 이 메소드는 대기중에 현재 Thread 객체의 interrupt() 메소드가 호출되면 InterruptedException이 던져진다.


void join(long mills)

호출한 메소드 스레드가 종료될 때까지 또는 지정한 시간동안 대기한다. 이 메소드는 대기중에 현재 Thread 객체의 interrupt() 메소드가 호출되면 InterrptedException이 던져진다.


void setDaemon(boolean isDaemon)

인자 isDaemon을 true로 지정하면 현재 Thread 객체와 연관된 스레드를 데몬 스레드로 설정한다. 스레드는 생성 또는 시작하기 전에 호출되면 java.lang.illegalThreadStateException이 던져진다.


void setName(String threadName)

인자 threadName의 값을 현재 Thread 객체 이름으로 지정한다.


static void sleep (long time)

지정한 시간(밀리 초) 만큼 현재 Thread 객체와 연관된 스레드를 일시 정지 시킨다. 스레드가 일지 정지되어 있는 동안 스레드 객체의 interrupt() 메소드가 호출되면 InterruptedException이 던져진다.


void start()

현재 Thread 객체와 연관되어있는 스레드를 생성하고 시작한다. 스레드가 이미 시작되어 실행중이거나 종료되어 있는 상태이면 IllegalThreadStateException을 던진다.



--------


package Thread;

public class CountingThreads {
    public static void main(String[] args){
        Runnable r=new Runnable() {
           
            @Override
            public void run() {
                String name=Thread.currentThread().getName();
                int count=0;
                while(true){
                    System.out.println(name+": "+count++);
                }
            }
        };

        Thread thdA =new Thread(r);
        Thread thdB=new Thread(r);
        thdA.start();
        thdB.start();
    }
}


기본 메인 스레드가 실행되는 main()에서는 우선 Runnable을 구현한 익명 클래스를 인스턴스화한다. 다음에 객체를 runnable로 초기화되는 두 개의 Thread객체를 생성한 후 스레드를 생성하고 시작하기 위해 Thread클래스의 start() 메소드를 호출한다. 이 작업들을 완료한 후 main() 메소드의 메인 스레드는 종료한다.


메인 스레드에서 시작된 두 스레드는 각각 runnable의 run() 메소드를 실행하는데 run()메소드에서는 Thread인스턴스를 획득하기 위해 Thread의 currentThread() 메소드를 호출한 후 getName()메소드를 호출하여 이름을 반환 받는다. 다음에 count를 0으로 초기화 시키고 name과 count의 값을 출력한 후 count 의 값을 증가기키면서 무한 반복한다.







'Java > Working-level Java' 카테고리의 다른 글

Thread 3  (0) 2015.01.14
Thread 2  (0) 2015.01.14
System  (0) 2015.01.06
StringBuffer / StringBuilder  (0) 2015.01.03
ChatClient  (0) 2014.12.26
Posted by af334
2015. 1. 6. 03:54
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

java.lang.System 클래스는 표준 입력, 표준 출력, 그리고 표준 에러를 포함한 시스템 지향적인 리소스에 접근할 수 있는 방법을 제공한다.


System 클래스에는 표준 입력, 표준 출력 그리고 표준 에러를 지원하는 각각의 in, out, 그리고 err클래스 필드가 선언되어 있다. in 클래스 필드는 java.io.InputStream 타입이며, out과 err클래스 필드는 java.io.PrintStream 타입으로 선언되어 있다. 이 클래스 필드들 이외에도 System 클래스에는 아래에서 소개하는 메소드를 포함하는 여러가지 static 메소드가 선언되어 있다.


void arraycopy (Object src, int srcPos, Object dest, int destPos, int length)

인자 src배열의 srcPos위치를 시작으로 인자 length에 지정한 개수의 요소를 인자 dest 배열의 destPos의 위치에 복사한다. 이 메소드는 인자 src 또는 dest가 null일 경우 NullPointerException을, 복사중에 배열의 범위를 벗어나게 되면 ArrayIndexOutBoundException을, 인자 src 배여로가 인자 dest배열의 타입이 일치하지 않아 저장을 못할 경우에는 java.lang.ArrayStoreException을 던진다.


long currentTimeMills()

January 1, 1970 00:00:00 UTC(universal time coordinated)에서부터 현재 시스템 시간까지의 시간을 밀리 초 단위로 반환한다.(UTC- 협정 세계시 :)


void gc()

JVM에게 가비지 콜렉터를 실행할 것을 통보한다. 하지만 통보를 했다고 해서 반드시 가비지 콜렉터가 실행되지는 않는다.


String getProperty(String prop)

인자 prop에 의해 지정된 시스템 프로퍼티(system property - 버전 번호 같은 플랫폼의 속성)의 값을 반환한다. 만일 지정한 프로퍼티가 존재하지 않으면 null을 반환한다.



void runFinalization()

JVM에 모든 불완전한 객체에 대해 파이널라이즈를 실행할 것을 통보한다. 단 이 메소드를 호출한다고 해도 반드시 객체들의 파이널라이즈가 수행되지는 않는다.


void setErr(PrintStream err)

표준 에러 스트림을 인자 err로 설정한다. 이 메소드 호출은 윈도우 xp에서 java Application2 > errlog로 지정하는 것과 같은 작업을 한다.


void setIn (InputStream in)

표준 입력 스트림을 인자 in으로 설정한다. 이 메소드 호출은 윈도우 xp에서 java Application < input 과 같이 지정하는 것과 같은 작업을 한다.


void setOut (PrintStream out)

표준 출력 스트림을 인자 out 으로 설정한다. 이 메소드 호출은 윈도우XP에서 java Application > output과 같이 지정하는 것과 같은 작업을 한다.



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



package System;

public class system {
    public static void main(String[] args){
        int[] grades={86,92,78,65,52,43,72,98,81};
        int[] gradesBackup=new int[grades.length];
        System.arraycopy(grades, 0, gradesBackup, 0, grades.length);
       
        for(int i=0; i<gradesBackup.length;i++)
            System.out.println(gradesBackup[i]);
       
            System.out.println("Current time : "+System.currentTimeMillis());
            String[] propNames={
                    "java.vender.url",
                    "java.class.path",
                    "user.home",
                    "java.class.version",
                    "os.version",
                    "java.vender",
                    "user.dir",
                    "user.timezone",
                    "path.separator",
                    "os.name",
                    "os.arch",
                    "line.separator",
                    "file.separator",
                    "user.name",
                    "java.version",
                    "java.home"
            };

            for (int i=0; i<propNames.length; i++){
                System.out.println(propNames[i]+": "+ System.getProperty(propNames[i]));
            }           
        }
    }


arraycopy(), currentTimeMills()그리고 getProperty()메소드를 사용하는 방법을 보여준다.

main() 메소드에서는 arraycopy()의 사용 방법을 제일 먼저 보여주는데 이 메소드는 grades 배열의 내용을 gradesBackup 배열에 복사를 한다.



arraycopy() 메소드는 배열을 다른 배열로 복사하는 가장 빠른 방법이다. 또한 참조를 내부 배열에 반환하는 메소드의 클래스를 작성할 때 배열의 복사본을 생성하고 복사본의 참조를 반환하기 위해 arraycopy() 메소드를 사용해야 한다. 이런 방법을 사용하면 고객이 직접 내부 배열을 조작하는 것을 방지 할 수 있다.


복사를 한 다음 밀리 초 값으로 표현되는 현재 시간을 반환하기 위해 currentTimeMills()메소드를 호출한다. currentTimeMills() 메소드에서 반환된 값이 밀리 초 형식으로써 일반적인 날짜는 아니기 때문에 날짜를 읽기 쉽게 하기 위새서는 일반적인 날짜 형식을 제공하는 java.util.Date클래스를 사용하는 것이 좋다. java.util.Date클래스의 Date()생성자는 내부적으로 currentTimeMills()를 호출한 후 toString()메소드에서 밀리 초의 값을 일반 형식의 날짜와 시간으로 변환한 후 반환한다.


마지막으로 main()메소드에서는 for 반복문 안에서 getProperty() 메소드를 사용하는데 반복을 하면서 프로퍼티의 이름과 값을 출력한다.



line.separator 프로퍼티에는 \r\n과 같은 줄바꿈을 표현하는 문자가 아닌 실제 줄 바꿈 문자 또는 문자들이 저장되어 있기 때문에 위의 출력 결과를 보면 line.separator 다음에 실제 빈 줄이 생긴다.











'Java > Working-level Java' 카테고리의 다른 글

Thread 2  (0) 2015.01.14
Thread  (0) 2015.01.06
StringBuffer / StringBuilder  (0) 2015.01.03
ChatClient  (0) 2014.12.26
ChatServer  (0) 2014.12.24
Posted by af334
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

실제 String 객체는 불변으로 String 객체의 문자열은 변경되지 않는다. String 객체의 경우 객체의 문자열이 변경되는 것처럼 보이지만 실제로는 변경된 문자열을 가진 새로운 String 객체가 반환되는 것이다. 그러므로 String 객체의 문자열을 자주 변경하게 되면 지속적으로 새로운 String 객체를 생성하기 때문에 리소스를 생각보다 많이 낭비하게 된다. 그래서 자바에서는 비효율적인 String 객체를 대신 할 수 있는 java.lang.StringBuffer와 java.lang.StringBuilder를 제공한다. StringBuilder클래스는 속도가 StringBuffer 보다는 빠르지만 명시적인 동기화(explicit syncronization)없이는 다중 스레드 컨택스트에서는 사용할 수 없다.


StringBuffer 객체를 초기화하고 문자열 버퍼를 다루는 StringBuffer에 포함되어 있는 자주 사용되는 생성자와 메소드를 소개한다.StringBuilder의 생성자와 메소드는 StringBuffer와 동일하다.


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

StringBuffer()   

기본적으로 16개의 문자를 저장할 수 있는 빈 배열로 StringBuffer 객체를 초기화 한다.


StringBuffer( int capacity)

인자 capacity에 지정한 크기의 문자를 저장할 수 있는 빈 배열로 StringBuffer객체를 초기화 한다. capacity의 값이 음수이면 java.lang.NegativeArraySizeException이 던져진다


StringBuffer( String s ) 

인자 s의 문자들을 갖는 배열로 StringBuffer 객체를 초기화한다. 객체의 기본 저장 크기인 16에 s의 길이가 더해진 배열이 만들어지는데 s가 null 이면 생성자에서 NullPointException을 던진다.


StringBuffer append( boolean b )

인자 b가 true이면 StringBuffer 객체의 배열에 문자열 "true"가 추가되고, 인자 b가 false이면 문자열 "false"를 추가한 후 추가된 StringBuffer객체를 반환한다.


StringBuffer append( char ch )

StringBuffer 객체의 배열에 인자 ch의 문자를 추가하고 추가된 StringBuffer 객체를 반환한다.


StringBuffer append( char[] chars )

StringBuffer 객체의 배열에 인자 chars 배열에 있는 문자들을 추가하고 추가된 StringBuffer 객체를 반환한다. 인자 char이 null이면 NullPointerException을 던진다.


StringBuffer append( double d )

StringBuffer 객체에 d의 배정밀도 부동 소수점 값을 문자열로 변경한 후 추가된 StringBuffer객체를 반환한다.


StringBuffer append( float f )

StringBuffer 객체의 배열에 인자 f의 부동 소수점 값을 문자열로 변경하여 추가한 후 추가된 StringBuffer객체를 반환한다.


StringBuffer append( int i )

StringBuffer 객체의 배열에 인자 i의 정수값을 문자열로 변경하여 추가한 후 추가된 StringBuffer 객체를 반환한다.


StringBuffer append( long l )

StringBuffer 객체의 배열에 인자 l의 배정수 값을 문자열로 변경하여 추가한 후 추가된 StringBuffer 객체를 반환한다.


StringBuffer append( Object obj )

StringBuffer 객체의 배열에 인자 obj의 toString() 메소드를 호출하여 반환된 문자열의 문자들을 추가한다. 만약 obj에서 null이 반환되면 "null" 이 StringBuffer 객체의 배열에 추가가 된다. 추가된 StringBuffer 객체를 반환한다.


StringBuffer append( String s )

StringBuffer 객체의 배열에 인자 s의 문자열을 추가한다. 만일 인자 s의 값이 null이면 "null"이 배열에 추가되고 추가된 StringBuffer 객체가 반환된다.


int capacity()

StringBuffer 객체의 배열에 저장 할 수 있는 문자의 수를 반환한다.


char charAt( int index )

StringBuffer 객체의 배열에서 인자 index가 가리키는 위치에 있는 문자를 반환한다. 만일 index의 값이 음수이거나 또는 StringBuffer 객체의 length 보다 크거나 같으면 StringIndexOutofBoundsException이 던져진다.


void ensureCapacity( int min )

StringBuffer 객체의 저장 용량을 인자 min에 의해 지정된 값보다 반드시 크게 설정한다. 만일 현재 저장 용량이 min보다 작으면 저장 용량을 크게 하기 위해 새로운 내부 배열이 생성되는데 새로운 저장 용량은 min보다 크게 설정된다. 추가되는 크기는 보통 현재 저장 용량에 2를 곱한 후 2를 더한 크기가 되며 만일 인자min값이 0 또는 음수일 때는 아무런 일도 일어나지 않는다.


int length()

StringBuffer 객체의 배열에 저장되어 있는 문자들의 수를 반환한다.


StringBuffer reverse()

StringBuffer 객체의 배열에 있는 내용의 순서를 반대로 바꾼 후 바뀐 StringBuffer 객체를 반환한다.


void setCharAt( int index, char ch )

인자 index로 지정한 위치에 있는 문자를 인자 ch의 값으로 변경한다. index의 값이 음수 또는 StringBuffer 객체의 length 길이보다 크거나 같으면 StringIndexOutofException이 던져진다.


void setLength( int length )

StringBuffer 객체의 배열 length를 지정한 length로 설정한다. 만일 인자로 지정된 length가 현재 length보다 작으면 배열의 내용이 짤리게 되며 인자로 지정된 length가 현재 length보다 크거나 같으면 배열이 추가되고 추가된 배열에는 null문자('\u0000')가 채워진다. length가 음수로 지정되면 StringIndexOutOfBoundsException을 던진다.


String substring( int start )

StringBuffer 객체의 배열에서 인자 start에 지정한 위치부터 배열의 마지막까지 있는 모든 문자를 포함하는 새로운 String 객체를 반환한다. 인자start가 0보다 적거나 StringBuffer 객체의 배열 length보다 크거나 같으면 StringIndexOutOfBoundsException이 던져진다.


String toString()

StringBuffer 객체의 배열에 있는 내용을 문자열로 갖는 새로운 String 객체를 반환한다.


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


StringBuffer 와 StringBuilder 객체의 내부 배열의 크기는 저장 용량과 길이로 구별된다. 저장 용량은 배열에 저장될 수 있는 문자의 최대 개수를 의미하며 길이는 배열에 현재 저장된 문자의 개수를 의미한다.


toAlignBinaryString() 메소드는 다음 드에서 볼 수 있듯 비효율적인 반복문으로 구현되어 있다


int numLeadingZeros=numBits-result.length();

String zeroPrefix="";

for (int j=0; j<numLeadingZeros; j++)

zerosPrefix+="0";


위의 코드에 있는 반복문은 반복될 때마다 StringBuilder 객체와 String 객체를 생성하기 떄문에 비효율적이다. 실제 컴파일러에서는 위의 코드를 다음과 같이 해석한다.


int numLeadingZeros=3;

String zerosPrefix="";

for(int j=0; j<numLeadingZeros; j++)

zerosPrefix = new Stringbuilder().append(zerosPrefix).append("0").toString();


반복문이 반복될 때마다 객체를 생성하는 위의 예를 좀더 효율적인 코드로 만들기 위해서는 StringBuffer/StringBuilder 객체를 반복문 전에 생성한 후 반복될 때마다 append() 메소드를 호출하고 반복이 끝난 후 toString() 메소드를 호출해야 한다. 다음 코드는 좀 더 효율적으로 작성한 것이다.


int numLeadingZeros=3;

StringBuilder sb=new StringBuilder();

for(int j=0; j<numLeadingZeros; j++)

sb.append("0");

String zerosPrefix= sb.toString();


**문자열 결함 연산자는 반복이 많이 되는 반복문에서 불필요하게 많은 StringBuilder와 String 객체를 생성하기 때문에 가급적 사용하지 않는 것이 좋다. **



















'Java > Working-level Java' 카테고리의 다른 글

Thread 2  (0) 2015.01.14
Thread  (0) 2015.01.06
System  (0) 2015.01.06
ChatClient  (0) 2014.12.26
ChatServer  (0) 2014.12.24
Posted by af334
2014. 12. 26. 03:04
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

package prac;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.xml.stream.events.StartDocument;

public class ChatClient {
    final static String SERVER_ADDR="localhost";
    final static int SERVER_PORT=8010;
    static Socket socket;
    static volatile BufferedReader br;
    static PrintWriter pw;
    static JButton btnSend;
    static JPanel createGUI(){
        JPanel pnlLayout=new JPanel();
        pnlLayout.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        pnlLayout.setLayout(new BorderLayout());
        JPanel pnlLeft =new JPanel();
        pnlLeft.setLayout(new BorderLayout());
        final JTextField txtUserName=new JTextField(30);
        pnlLeft.add(txtUserName, BorderLayout.NORTH);
        final JTextArea txtInput =new JTextArea(5,30);
        txtInput.setEnabled(false);
        pnlLeft.add(new JScrollPane(txtInput), BorderLayout.CENTER);
        final JTextArea txtOutput =new JTextArea(10,30);
        txtOutput.setFocusable(false);
        pnlLayout.add(new JScrollPane(txtOutput), BorderLayout.SOUTH);
        pnlLayout.add(pnlLeft,BorderLayout.WEST);
        JPanel pnlRight =new JPanel();
        pnlRight.setLayout(new BorderLayout());
        final JTextArea txtUsers=new JTextArea(10,10);
        txtUsers.setFocusable(false);
        Border border=BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
        txtUsers.setBorder(border);
        pnlRight.add(txtUsers, BorderLayout.NORTH);
        JPanel pnlButtons=new JPanel();
        pnlButtons.setLayout(new GridLayout(3,1));
        final JButton btnConnect =new JButton("Connect");
        ActionListener al;
        al=new ActionListener() {
           
            @Override
            public void actionPerformed(ActionEvent ae) {
                txtUserName.setFocusable(false);
                String username=txtUserName.getText().trim();
                try {
                    socket=new Socket(SERVER_ADDR, SERVER_PORT);
                    btnConnect.setEnabled(false);
                    InputStreamReader isr;
                    isr=new InputStreamReader(socket.getInputStream());
                    br=new BufferedReader(isr);
                    pw=new PrintWriter(socket.getOutputStream(), true);
                    txtOutput.append(br.readLine()+ "\n");
                    pw.println((!username.equals(""))?username:"unknown");
                    txtInput.setEnabled(true);
                    btnSend.setEnabled(true);
                    new Thread(new Runnable() {
                       
                        @Override
                        public void run() {
                            String line;
                            try {
                                while ((line=br.readLine())!=null) {
                                    if (line.charAt(0)!='!'){
                                        txtOutput.append(line+"\n");
                                        continue;
                                    }
                                    txtUsers.setText("");
                                    String[] users;
                                    users=line.substring(1).split(" ");
                                    for (String user : users) {
                                        txtUsers.append(user);
                                        txtUsers.append("\n");
                                    }
                                }
                            } catch (IOException ioe) {
                                txtOutput.append("lost the link");
                                return;
                            }
                        }
                    }).start();
                   
                } catch (Exception e) {
                    txtOutput.append("unable to connect to server");
                }
            }
        };
       
        btnConnect.addActionListener(al);
        pnlButtons.add(btnConnect);
        btnSend=new JButton("Send");
        btnSend.setEnabled(false);
        al=new ActionListener() {
           
            @Override
            public void actionPerformed(ActionEvent ae) {
                pw.println(txtInput.getText());
                txtInput.setText("");
            }
        };
        btnSend.addActionListener(al);
        pnlButtons.add(btnSend);
        JButton btnQuit=new JButton("Quit");
        al=new ActionListener() {
           
            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    if(socket!=null)
                        socket.close();
                   
                } catch (IOException ioe) {
                }
                System.exit(0);
            }
        };
        btnQuit.addActionListener(al);
        pnlButtons.add(btnQuit);
        pnlRight.add(pnlButtons, BorderLayout.SOUTH);
        pnlLayout.add(pnlRight, BorderLayout.EAST);
        return pnlLayout;
    };
   
    public static void main(String[] args){
        Runnable r =new Runnable() {
           
            @Override
            public void run() {
                JFrame f =new JFrame("ChatClient");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setContentPane(createGUI());
                f.pack();
                f.setResizable(false);
                f.setVisible(true);
            }
        };
        EventQueue.invokeLater(r);
    }
}








'Java > Working-level Java' 카테고리의 다른 글

Thread 2  (0) 2015.01.14
Thread  (0) 2015.01.06
System  (0) 2015.01.06
StringBuffer / StringBuilder  (0) 2015.01.03
ChatServer  (0) 2014.12.24
Posted by af334
이전버튼 1 2 이전버튼