[Java/Theory]30. Socket Mechanism


[Java/Theory]29. Lambda Expression

출처 : 

https://en.wikipedia.org/wiki/Lambda_expression

http://jdm.kr/blog/181

https://www.tutorialspoint.com/java8/java8_lambda_expressions.htm


정의 

식별자(identifier)로 binding되지 않은채 정의된 함수. 

Java 8 부터 지원하는 표현식으로서, 함수형 프로그래밍을 도입한다.

가독성과 간편성의 목적을 두고있고, 객체지향의 큰 특징인 다형성을 활용했다.


특징

유형 정의, 괄호와 중괄호((), {}), 반환값 정의에 독립적.

차후 예제에서 확인한다.

   

기존 사용법.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package example;
 
public class PreviousThread {
    
    public static void main(String args[]){
        
        Thread thread = new Thread (new Runnable(){
 
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("There is no rule without exception.");
            } // end of run
            
        }); // end of definition to thread variable
        
        thread.start();
        
    } // end of main
    
// end of PreviousThread
cs


기본적인 사용법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package example;
 
public class LambdaThread {
 
    public static void main(String args[]){
        
        Thread thread = new Thread(() ->{
            System.out.println("There is no rule without exception.");
        });
        
        thread.start();
        
    } // end of main
    
}// end of LambdaThread
cs


주의점

Lambda Expression을 활용하기 위해서 대상 Interface는 abstract method를 단 하나만 보유해야된다. 또한 Lambda Expression을 사용하는 목적으로 설계된 Interface는 정의할 때 Annotation을 이용하여 명시하도록 한다. 물론 표기하지 않아도 되나, 여러가지의 오류를 아래의 예제로 두도록 하겠다. 이는 Compiler 수준에서 오류를 확인 할 수 있다는 것을 알 수있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package example;
 
public class ExOfLambda {
 
    interface Cal{
        int add(int a, int b);
        int sub(int a, int b);
    }
    
    public static void main(String args[]){
        
        // Syntax Error 
        // The target type of this expression must be a function interface
        Cal cal = (int a, int b) -> a+b;
        
    } // end of main
    
}// end of ExOfLambda
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package example;
 
public class ExOfLambda {
 
    // Syntax Error
    // Invalid '@FunctionalInterface' annotation; ExOfLambda.Cal is not a functional interface.
    @FunctionalInterface
    interface Cal{
        int add(int a, int b);
        int sub(int a, int b);
    }
    
    public static void main(String args[]){
        
        // Syntax Error 
        // The target type of this expression must be a function interface
        Cal cal = (int a, int b) -> a+b;
        
    } // end of main
    
}// end of ExOfLambda
 
cs


올바른 예제는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package example;
 
public class ExOfLambda {
 
    @FunctionalInterface
    interface Cal{
        int add(int a, int b);
    }
    
    public static void main(String args[]){
        
        Cal cal = (int a, int b) -> a+b;
        
        System.out.println(cal.add(12));
        
    } // end of main
    
}// end of ExOfLambda
 
cs


특징을 이용한 활용법.

유형 정의, 괄호와 중괄호((), {}), 반환값 정의에 독립적이라 하면 활용하는 예제는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package example;
 
public class ExOfCharacter {
 
    @FunctionalInterface
    interface Calculation {
        int go(int aaa, int bbb);
    } // end of Calculation
 
    @FunctionalInterface
    interface Message {
        void go(String message);
    } // end of Message
 
    public static void main(String args[]) {
 
        // 매개변수 유형 사용
        Calculation addition = (int nnn, int yyy) -> nnn + yyy;
        System.out.println("매개변수 유형 사용");
        System.out.println(addition.go(1,2));
 
        // 매개변수 유형 미사용
        Calculation subtraction = (kkk, hhh) -> kkk - hhh;
        System.out.println("매개변수 유형 미사용");
        System.out.println(subtraction.go(1,2));
 
        // 반환값과 중괄호 사용
        Calculation multiplication = (int lll, int ddd) -> {
            return lll * ddd;
        };
        System.out.println("반환값과 중괄호 사용");
        System.out.println(multiplication.go(1,2));
        
        // 반환값과 중괄호 미사용
        Calculation division = (int www, int fff) -> www / fff;
        System.out.println("반환값과 중괄호 미사용");
        System.out.println(division.go(1,2));
 
        // 매개변수 괄호 사용
        Message secondMessage = (message) -> System.out.println(message);
        System.out.println("매개변수 괄호 사용");
        secondMessage.go("firstMessage");
 
        // 매개변수 괄호 미사용
        Message firstMessage = message -> System.out.println(message);
        System.out.println("매개변수 괄호 미사용");
        firstMessage.go("secondMessage");
 
    } // end of main
 
// end of ExOfCharacter
cs

어떤걸 사용하면 되냐고 묻는다면, 니 맘대로 하세요.


또 다른 활용.

Excutor 포스트에서 invokeAny의 예제를 참조한다면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package example;
 
public class ExOfHelperMethod {
 
    interface Calculation {
        int go(int aaa, int bbb);
    } // end of Calculation
    
    static Calculation getCalculation(int ccc, int ddd){
        return (aaa, bbb)->{
            return aaa + bbb + ccc + ddd;
        };
    } // end of getCalculation
 
    public static void main(String args[]) {
 
        // aaa = 3
        // bbb = 4
        // ccc = 1
        // ddd = 2
        Calculation cal = getCalculation(12);
        System.out.println(cal.go(34));
 
    } // end of main
 
// end of ExOfCharacter
cs


[Java/Theory]28. Executor

(출처 : http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/)

Java 8 에서 병행처리중 두 가지 사용법이Thread와 Executor가 있다.

먼저 Thread를 보도록 한다.


Thread & Runnables

현대 운영체제는 process와  thread를 통해 병행처리를 지원한다. process는 서로 간에 독립적으로 실행하는 program의 단위이다. 이 process 내부에서 thread가 병행하여 code를 실행 될 수있다. thread는 JDK 1.0이후로 자바에서 지원하는데, 시작하기 앞서 code가 task라 부르는 thread에 의해 실행된다는 사실을 알아야 된다. 이는 Runnable을 실행시켜서 작업하게 된다.

간단한 Thread를 예문을 들면, 실행결과는 때에 따라 다르다. 응용 프로그램이 커질수록 복잡 할 수 있다. 또한 Thread는 sleep이란 것을 특정 시간에 사용할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package example;
 
public class ExOfThread {
    
    public static void main(String args[]){
        Runnable task = () -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("Hello " + threadName);
        };
 
        task.run();
 
        Thread thread = new Thread(task);
        thread.start();
 
        System.out.println("Done!");
 
    }
    
}
 
cs


1
2
3
Hello main
Done!
Hello Thread-0
cs


1
2
3
Hello main
Hello Thread-0
Done!
cs


Executor

병행처리 API는 thread와 작동하는 ExecutorService의 개념으로 시작된다.  Executor는 thread들을 pool로 관리하고 task를 비동기로 실행시킨다. 그래서 굳이 Thread를 생성할 필요가 없다. 내부적으로 있는 pool의 모든 thread들이 반복적 작업을 수행하기 위해 재사용될 것이다?(All threads of the internal pool will be reused under the hood for revenant tasks ) 그러니 단일적으로 ExecutorService로 작동하는 응용 프로그램에 있는 생명주기에 따라 병행처리 작업이 가능하다.

간단한 예시는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package example;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class ExOfExecutor {
    
    public static void main(String args[]){
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("Hello " + threadName);
        });
 
    }
    
}
 
cs


Executor는 서로 다른 ExecutorService를 생성하는 편리한 factory method를 제공한다. 위 예제는 thread pool 크기가 하나인 경우다. 실행 결과는 위에 있는 thread 예제와 비슷하지만 명백히 중요한 차이점이 있다. Executor의 경우 java process가 종료되지 않는다. 그러므로 명시적으로 종료시켜야 된ㄷ다. 그렇지 않으면 새 작업을 계속 듣게 된다.

ExecutorService는 shutdown(), shutdownNow()라는 두 method를 재공하는데 shutdown()은 현재 실행중인 작업을 종료시키기 위해 대기하고 shutdownNow()는 모든 작업을 막고 executor를 즉각 꺼버린다. 예제는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package example;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
 
public class ExOfShutdown {
    
    public static void main(String args[]){
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(() -> {
            try {
                System.out.println("attempt to shutdown executor");
                executor.shutdown();
                executor.awaitTermination(5, TimeUnit.SECONDS);
            }
            catch (InterruptedException e) {
                System.err.println("tasks interrupted");
            }
            finally {
                if (!executor.isTerminated()) {
                    System.err.println("cancel non-finished tasks");
                }
                executor.shutdownNow();
                System.out.println("shutdown finished");
            }
        });
        
 
 
    }
    
}
 
cs


1
2
3
attempt to shutdown executor
cancel non-finished tasks
shutdown finished
cs


Executor가 현재 작업을 실핼 시키면서, 특정 시간동안 대기하다가 그 시간이 지나면 모든 작업을 막고 종료시킨다.


Callable and Fututre

Runnable을 추가로 하여서, Executor는 Callable이란 또 다른 작업을 지원한다. 이 funcrional interface는 Runnable과 비슷하지만 Callable은 return 값이 있다.

Callable<Integer> task = () -> {
    try {
        TimeUnit.SECONDS.sleep(1);
        return 123;
    }
    catch (InterruptedException e) {
        throw new IllegalStateException("task interrupted", e);
    }
};


Callable은 Runnable처럼 ExecutorService에게 submit()를 통해 전달 될 수 있다. 

그러나 submit()는 작업이 끝나기 전까지 대기하지 않기 때문에 ExecutorService는 Callable의 결과를 return value를 직접 나타낼 수 업다. 그리하여 차후에 결과를 회수하는데 사용 될 수있는 Future라는 결과값을 나타낼 수있다.

ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(task);

System.out.println("future done? " + future.isDone());

Integer result = future.get();

System.out.println("future done? " + future.isDone());
System.out.print("result: " + result);

Callable을 Executor에 전달하고 가장 먼저 확인할 것은 Future가 isDone()을 통해서 완료가 됐는가 아닌가를 보는 것이다.

분명히 첫 번째에 있는 isDone은 정수값을 반환하기 전에 1초간 잠들고 있는 이후가 아니므로 false로 나타날 것이고, get()이란 method가 현재 thread를 막고 Callable의 실제 반환값 123을 전달하기까지 Callable의 완료를 대기하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package example;
 
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
 
public class ExOfCallableFuture {
 
    public static void main(String args[]) {
        Callable<Integer> task = () -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                return 123;
            } catch (InterruptedException e) {
                throw new IllegalStateException("task interrupted", e);
            }
        };
 
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(task);
 
        System.out.println("future done? " + future.isDone());
 
        Integer result = null;
        try {
            result = future.get();
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("future done? " + future.isDone());
        System.out.print("result: " + result);
 
    }
 
}
 
cs
future done? false
future done? true
result: 123

Future는 근본적으로 ExecutorService와 탄탄히 결합되어있다?(Future are tightly coupled to the underlying executor service.) 종결되지 않은 모든 furture는 executor가 shutdown되면 예외를 던지게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package example;
 
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
 
public class ExOfCallableFuture {
 
    public static void main(String args[]) {
        Callable<Integer> task = () -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                return 123;
            } catch (InterruptedException e) {
                throw new IllegalStateException("task interrupted", e);
            }
        };
 
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(task);
 
        System.out.println("future done? " + future.isDone());
 
        Integer result = null;
        try {
            executor.shutdownNow();
            result = future.get();
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("future done? " + future.isDone());
        System.out.print("result: " + result);
 
    }
 
}
 
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
future done? false
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: task interrupted
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at example.ExOfCallableFuture.main(ExOfCallableFuture.java:30)
Caused by: java.lang.IllegalStateException: task interrupted
    at example.ExOfCallableFuture.lambda$0(ExOfCallableFuture.java:18)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at example.ExOfCallableFuture.lambda$0(ExOfCallableFuture.java:15)
    ... 4 more
future done? true
result: null
cs


Executor를 생성하는데 있어 newFixedThreadPool(int)를 사용하면 thread를 한 개만 허용하는thread pool의 executor service를 생성한다. 이는 newSingleThreadExecutor()와 동일하지만 앞으로도 1개 이상의 값들을 전달해야되므로 pool의 크기를 늘려야할 필요가 있다.


Timeouts

future.get()은 Callable이 종결되기 전까지 대기한다. 최악의 경우, Callable이 계속 실행된다는 점인데, 무반응의 응용 프로그램이 되기 마련이다. 이에 대응하여 timeout이라는 시나리오를 작성해본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package example;
 
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
 
public class ExOfTimeout {
 
    public static void main(String args[]) {
        ExecutorService executor = Executors.newFixedThreadPool(1);
 
        Future<Integer> future = executor.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                return 123;
            }
            catch (InterruptedException e) {
                throw new IllegalStateException("task interrupted", e);
            }
        });
 
        try {
            future.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
}
 
cs


1
2
3
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at example.ExOfTimeout.main(ExOfTimeout.java:26)
cs

이 예외가 발생되는 이유는 get()에서 최대 대기 시간을 1초로 했는데, sleep시간을 2초로 지정했기 때문이다.


InvokeAll

Callable과 Future를 list로 표현할때, 이에 대한 접근은 invokeAll()을 통해서 Executor에게 전달한다. Executor는 일괄적으로 callable을 전달하게끔 지원한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package example;
 
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class ExOfInvokeAll {
 
    public static void main(String args[]) {
        ExecutorService executor = Executors.newWorkStealingPool();
 
        List<Callable<String>> callables = Arrays.asList(
                () -> "task1",
                () -> "task2",
                () -> "task3");
 
        try {
            executor.invokeAll(callables)
                .stream()
                .map(future -> {
                    try {
                        return future.get();
                    }
                    catch (Exception e) {
                        throw new IllegalStateException(e);
                    }
                })
                .forEach(System.out::println);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
}
 
cs

이 예제는 invokeAll이 발동되어 반환된 모든 Callable을 처리하기 위해 Java 8에서 제공하는 Stream을 이용한 것이다.


InvokeAny

invokeAll()외에 일괄적으로 Callable을 Executor에 전달하는 방법은 invokeAny()가 있다.

이는 invokeAll()과 다르게 모든 객체들을 반환하지 않고, 최초 완료한 객체가 나오기까지 객체들의 반환을 막아놓고 있다가 그 최초의 객체를  반환시킨다. (Instead of returning future objects this method blocks until the first callable terminates and returns the result of that callable.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package example;
 
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
 
public class ExOfInvokeAny {
 
    public static Callable<String> callable(String result, long sleepSeconds) {
        return () -> {
            TimeUnit.SECONDS.sleep(sleepSeconds);
            return result;
        };
    }
    
    public static void main(String args[]) {
        
        ExecutorService executor = Executors.newWorkStealingPool();
 
        List<Callable<String>> callables = Arrays.asList(
            callable("task1"2),
            callable("task2"1),
            callable("task3"3));
 
        String result = null;
        try {
            result = executor.invokeAny(callables);
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(result);
 
        // => task2
    }
    
 
}
 
cs

위 예제의 경우 Callable들을 모아놓은 List에서 sleep 시간이 가장 먼저 끝나는 Callable이 task2인데 결과를 출력하면 task2가 나오게 하여금 invokeAny를 활용하였다.


Executor를 생성하는 newWorkStealingPool()은 Executor의 한 종류인 ForkJoinPool을 반환하는데 일반적인 Executor와 조금 차이가 있다. ...(Instead of using a fixed size thread-pool ForkJoinPools are created for a given parallelism size which per default is the number of available cores of the hosts CPU.

[Java/Theory]26. 이클립스 관련 클래스패스 문제


http://egloos.zum.com/entireboy/v/4316863

[Java/Theory]25. I/O에 있는 각 클래스별 차이점 비교분석

(참고문헌 : Java Application Programming Interface)


BufferedWriter VS PrintWriter

BufferedWriter

Writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.

The buffer size may be specified, or the default size may be accepted. The default is large enough for most purposes.

A newLine() method is provided, which uses the platform's own notion of line separator as defined by the system property line.separator. Not all platforms use the newline character ('\n') to terminate lines. Calling this method to terminate each output line is therefore preferred to writing a newline character directly.

In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,

 PrintWriter out
   = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
 

will buffer the PrintWriter's output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.


PrintWriter

Prints formatted representations of objects to a text-output stream. This class implements all of the print methods found in PrintStream. It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.

Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the printlnprintf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.

Methods in this class never throw I/O exceptions, although some of its constructors may. The client may inquire as to whether any errors have occurred by invoking checkError().




[Java/Theory]24. I/O Object전송과 Serialization


http://hyeonstorage.tistory.com/252

http://hyeonstorage.tistory.com/254

23. JDBC

    DB의 SQL을 자바와 연결해 주는것을 표준화 한 체계

    각 RDBMS(Vendor)마다, 다형성이 입각된 체계로서, DB와 연결하는 것.

    JDBC 내부에는 Java진영(java.sql.*)과 RDBMS를 연결해주는 Driver(Vendor)들이 있다.

    이 Driver는 Vendor마다 존재하며, JRE가 따로 설정된 classpath를 통해 Driver(jar)를 연결한다.

    JRE는 ByteCode의 Query문을 이용하여 JDBC를 통해 DB에 있는 내용을 가져온다.


  * JDBC의 절차

      1. DBMS접근 : Connection(interface)으로 Objcet Modeling. (ID, PASSWORD, URL을 Encapsulation)

      2. Query    : Statement(interface)으로 Objcet Modeling. (DML, DCL, Query를 Encapsulation)

      3. View     : ResultSet(interface)으로 Object Modeling. (Query의 결과를 Encalsulation)


  * 세부적 절차

      java.sql에 있는 Connection, Statemant, ResultSet은 Interface로 구성되어 있다.

      이들의 Method는 바로 사용 할수 없으나 RDBMS의 Driver를 이용하여 사용 할 수 있다.

      먼저 Driver의 경로에 맞게 Classpath를 설정한다.


     

      방법 1. RDBMS의 Driver를 import하여 해당 RDBMS의 Driver Instance를 생성한다.

              다형성을 입각하여, SQL API들이 Driver Instance를 참조하게 한다.


      방법 2. java.lang에 있는 Class라는 Class에 forName이라는 Static Method가 있다.

              이 Method의 역할은 Argument를 이용하여 관련된 Class나 Interface가 메모리에 적재된다.

              적재된 Class를 적용하면 방법1의 과정없이 SQL의 API를 이용할 수 있다.

              => Programming based on interface


              Ex : 

1
2
3
4
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connect = DriverManager.getConnection(url, user, pwd);
Statment stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery("select * from ~~");
cs


      DB 작업이 종료되면 관련 변수들은 모두 close()시킨다.

 

  * Method

      - Statement

        execute(String sql)

        SQL종류를 모를경우


        executeQuery(String sql)

        실행 결과를 받기 위한 Method. ResultSet형태로 반환된다.        


        executeUpdate(String sql)

        해당 Query를 수행하는데, DML의 경우 수정된 행만큼 반환된다.

        DDL같은 경우 0으로 반환된다.


  * Statement VS PreparedStatement

      Statement : 모든게 완성된 일반 Query

                  Query를 실행하는 시점에 매번 Compile

                  PreparedStatement보다 상대적으로 느림


      PreparedStatement : 변수처럼 변경될 데이터 부분은 ?로 처리

                          ?로 처리된 부분을 제외한 Query가 미리 Compile되어 실행 효율을 높인다.

                          setInt, setString으로 해당 ?의 Index와 값을 대입하여 처리한다.

                          Single Quotation과 Double Quotation의 혼란을 덜어준다.


      CollableStatement : 다른 Statement와 유사하나 PL/SQL에 확장되어 DB에 종속적인 개발을 하게된다.

                          


  * TCL(Transaction Control Language)

      특정 Query를 진행하는 도중 예기치 못한 상황이 발생되어 중단되면, 그만큼의 손실이 발생된다.

      이 Query는 원자성을 유지해야 되기 때문에 commit, rollback으로 통제하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
try {
    // registering Oracle driver class
    Class.forName("oracle.jdbc.driver.OracleDriver");
 
    // getting connection
    con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",
                                        "ankit""Oracle123");
    System.out.println("Connection established successfully!");
 
    con.setAutoCommit(false); //Now, transactions won't be committed automatically.
    stmt = con.createStatement();
 
    //Execute first update statement - update salary of employee with id=1
    stmt.executeUpdate("UPDATE EMPLOYEE set salary=14000 where id=1 ");
 
    //Let's say first update statement was executed successfully.
    //Execute second update statement - update salary of employee with id=2
    stmt.executeUpdate("UPDATE EMPLOYEE set salary=15000 where id=2 ");
 
    /*
        IF ANY THING GOES WRONG IN EXECUTING SECOND UPDATE, control will go to
        catch block, rollback() method will be called and any changes done
        by first update statement will be rolled back.
    */         
    System.out.println("Salary of both employees was updated successfully");
 
    con.commit(); //commit all the transactions
 
catch (Exception e) {
    e.printStackTrace();
    try {
        con.rollback(); //In case of Exception, rollback all the transactions
        System.out.println("Salary of employees wasn't updated, rollback done");
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
finally {
    try {
        if(stmt!=null) stmt.close(); //close Statement
        
        if(con!=null) con.close(); // close connection
    
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
cs

 



'Java > Theory' 카테고리의 다른 글

[Java/Theory]25. I/O에 있는 각 클래스별 차이점 비교분석  (0) 2016.07.31
[Java/Theory]24. I/O Object전송과 Serialization  (0) 2016.07.29
[Java/Theory]23. JDBC  (0) 2016.05.31
[Java/Theory]22. Thread  (0) 2016.05.31
[Java/Theory]21. Maker Interface  (0) 2016.05.31
[Java/Theory]20. IO  (0) 2016.05.31

22. Thread(Multi - Thread)

    * Process : 실행중인 프로그램

    * Thread : 프로세스에서 실행되는 흐름의 단위

    * 사용이유 : 여러개의 프로세스를 실행하면 메모리에 부담이 되므로

                    하나의 프로세스에 여러가지의 처리를 하는 것이 메모리와 운영체제 입장에서 효율적이다.  


  * Java에서 동작되는 Thread의 원리

      JVM에는 Thread Scheduler가 있다.

      이 곳에서 기본적으로 동작되는 Thread가 main method다.


      Thread Scheduler에 다른 Thread를 진입하기 위해서는 

      start method를 가진 Instance가 필요하다.


      Thread Scheduler에 유일하게 접근이 가능한 start는

      Thread를 구현한 run을 Thread Scheduler에 위임한다.


      Thread Scheduler에 Thread를 알맞게 Scheduling한 JVM은

      운영체제에 있는 Process Scheduler에 전달하여

      해당 Process를 동작 시킬 수 있다.


  * 구현방법

      하나.

1
2
3
4
5
6
7
8
9
10
public class ThreadTest extends Thread{
    public void run(){
        // implementation
    }
 
    public static void main(String [] args){
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }
}
cs

    

      두울

1
2
3
4
5
6
7
8
9
10
11
public class ThreadTest extends SuperClass implements Runnable{
    public void run(){
        // implementation
    }          
 
    public static void main(String [] args){
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest);
        thread.start();
    }           
}
cs


  * Thread의 특징

      Thread는 운영체제와 해당 Thread의 Data 자원을 공유하고 있다.

      그러나 이 자원들을 공유하는데 있어 한 Thread가 자원을 점유 할 때,

      다른 Thread도 같이 점유하게 되어 자원의 일관성에 대한 문제가 발생된다.

      이러한 문제를 동기화 문제라고 한다.


      ->synchronized

        동기화 문제를 해결하기 위한 Keyword

        synchronized로 처리된 Instance는 자원접근을 위한 Key를 갖게된다.

        선언된 Thread가 자원에 접근할 때, 그 Key를 가지고 자원을 사용하고 반납하는 주기를 갖는다.

        이때, JVM은 다른 Thread가 자원을 접근하는 것을 막아놓는다.


    * Method에 선언

          해당 Method가 실행되고 있는 동안에 동기화를 보장한다.        


    * Block구간에 선언

1
2
3
synchronized (this)    {
    // implementation
}
cs

          여기서 사용된 this 객체는 자기 자신 

          즉, 현재 이 Method를 수행하고 있는 객체에 대해서 동기화를 시킨다는 의미다.


    * Overhead

          동기화 구문이 커질수록 다른 작업은 그에 따라 작업 수행 속도가 저하될 수 있다.


          여러 Thread가 여러 자원에 대해서 독립적으로 동기화 되어야 하기 때문에

          synchronized가 발생되는 동안에는 해당 구간에 대해서만 동기화를 확실히 수행하는 것이다.


          Block구간에 선언하여 Overhead를 최소화 한다.


    * Deadlock

          두 Thread가 자원을 가진 상태에서, 서로 자원의 점유를 해제하기만을 기다리는 상황으로 

          작업이 진행되지 않고 영원히 기다리게 되는 상황을 말한다.


   * Thread Life Cycle

      구성

      1. Runnable : start()에 의한 Thread들이 실행하기전 대기하는 영역

                    FIFO구조.

      2. Run :      Scheduler에 의하여, 한개의 Thread가 실행하는 영역

      3. Blocked :  특정 Method(wait, sleep, join, intterupt)나 Scheduler등의 이유로 

                    Thread가 대기하는 영역.

                    Synchronized pool, Sleep pool등등이 있다. 

                    notify나 shynchronized에 의하여 이 곳에 있는 Thread는

                    Runnable에 대기한다.(중간에 들어갈 수 있음)


      4. Dead    : 해당 Thread가 끝나면 들어가는 영역. 재생성 불가.

'Java > Theory' 카테고리의 다른 글

[Java/Theory]24. I/O Object전송과 Serialization  (0) 2016.07.29
[Java/Theory]23. JDBC  (0) 2016.05.31
[Java/Theory]22. Thread  (0) 2016.05.31
[Java/Theory]21. Maker Interface  (0) 2016.05.31
[Java/Theory]20. IO  (0) 2016.05.31
[Java/Theory]19. interface기반, Inner class, instanceof  (0) 2016.05.31

21. Maker Interface

    Serializable이라는 Interface로 Implemented한 Class.

    Data를 주고받기 위한 목적으로 둔 Class에 사용된다.

    Maker Interface로 설정해두면 JVM은 그 Class가 JVM외부로 나갈 수 있다고 인식된다.

    이를 객체 직렬화라고 부른다.


  * Application Protocol

      C/S간에 Data를 주고 받기 위한 통신규약


  * ValueObject

      객체 직렬화된 Object.

      이름 뒤에 VO라 작성하는 것이 약속이다.

      Application Protocol을 보완하였다.

      VO를 주고 받기 위해 사용 되는 Class는

      ObjectInputStream과 ObjectOutputStream이다.

'Java > Theory' 카테고리의 다른 글

[Java/Theory]23. JDBC  (0) 2016.05.31
[Java/Theory]22. Thread  (0) 2016.05.31
[Java/Theory]21. Maker Interface  (0) 2016.05.31
[Java/Theory]20. IO  (0) 2016.05.31
[Java/Theory]19. interface기반, Inner class, instanceof  (0) 2016.05.31
[Java/Theory]18. Exception Handling  (0) 2016.05.31

20. IO

    JRE내부에는 자바를 실행하는 Bytecode가 있다. 

    이 Bytecode의 내, 외부를 조작 할 수 있는것이 IO Package다.

    IO에는 크게 5가지로 분류된다.


    ~Stream : 바이트(이진) 단위로 입출력을 수행하는 Class

    ~Reader / ~Writer :  Charactor 단위로 입출력을 수행하는 Class


//    File~ : 하드디스크의 파일을 사용하는 Class

//    Data~ : 자바의 원시 자료형을 출력하기 위한 Class

//    Buffered~ : 시스템의 버퍼를 사용하는 Class


 * InputStream / OutputStream (바이트 입출력)

      Abstract Class


 * Reader / Writer (문자 입출력)

      Abstract Class


      4개의 Abstract Class간에 is a 관계가 성립되지 않으나,

      Polymorphism을 위한 Consistency가 확립되어 있다.

      Checked Exception중에 IOException을 지원한다.


    *  InputStreamr과 Reader는 서로 다른 Datatype이지만

       InputStream으로 처리하던 중 Charactor를 읽어야 하는 상황이 온다면

       Reader로 변경이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
// 표준 입력장치를 추상화 한것이 System.in이다.
// API에 따르면 System.in의 Datatype은 InputStream으로 되어 있으나
// getClass()로 확인하면, BufferedInputStream으로 되어 있으므로
// 아래 구문은 Implicit Casting이 되어 read() Method를 사용 할 수 있다.
// read()는 Checked Exception중에 IOException을 지원하므로 try - catch에 포함시키도록 한다.
InputStream inputStream = System.in
Reader reader = new InputStreamReader(inputStream);
 
int i = reader.read();
char c = (char)i;
// 출력된 c중에 공백 2자가 있다. 이를 이용하여 알아서 잘 코딩 하셈.
System.out.println("입력한 값 : " + c);
cs


    * 출력을 할때, integer와 charactor를 변경하는 불편함이 있으므로, Writer를 이용하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
try{
    InputStream inputStream = System.in
    Reader reader = new InputStreamReader(inputStream);
 
    // 표준 입력장치를 추상화 한것이 System.out이다.
    // API에 따르면 System.out의 Datatype은 OutputStream으로 되어 있으나
    // getClass()로 확인하면, BufferedOutputStream으로 되어 있으므로
    // 아래 구문은 Implicit Casting이 되어 write() Method를 사용 할 수 있다.
    // write()는 Checked Exception중에 IOException을 지원하므로 try - catch에 포함시키도록 한다.
    OutputStream outputStream = System.out;
    Writer writer = new OutputStreamWriter(outputStream);
 
    while(true){
        int i = reader.read();
        writer.write(i);
        // JRE에는 사용자가 입력한 값들을 모아두는 Buffer가 있다.
        // flush()는 모아둔 Buffer들을 모두 내뱉어, 출력하는 함수다.
        // 때문에 flush를 어디에 작성해야 되는가를 잘 파악 해 두도록 한다.
        //writer.flush();  
 
        if((char)i =='x'){
            break;
        }
    } // end of while
 
    writer.flush();
    
    // Stream close
    // close에는 flush가 내포되어 있다.         
    reader.close();
    writer.close();
 
}catch(IOException e){
    e.printStackTrace();
}
cs


    * In = Read의 개념

      통상적으로 DataSource라고 부른다.


  * Out = Write의 개념

      통상적으로 DataTarget라고 부른다.      


  * Java IO의 특징

      - Simplex Modeling

        각 Class마다 Read와 Write기능이 따로 정의되어 있음.

      - FIFO

      - IO Block

        입력이 올 때까지 시스템은 Wating한다.

      - Flexible Structure

        Polymorphism이 입각한 Filter Stream이 구현되는 구조.

        ->Sink Stream : Data를 직접 주고 받는 단순 IO.

        ->Filter Stream : Sink Stream을 통해 들어오는 Data를 조작하는 Stream

           Ex 1 : 

1
2
BufferedReader bufferedReader = new BufferedReader ( new InputStreamReader ( new FileInputStream ( "text.txt" , true) ) ) ;
// true => append 기존 파일에 있는 내용에 추가한다.
cs

        -> 조작 상황에 따라 Sink와 Filter를 활용한다.


  * Exception Handling의 주의할 점

      NullPointerException에 유의하도록 finally구문에 null check를 하는 습관을 기르도록 한다.


  * Relative Path

      Classpath에 지정된 곳을 Root로 출발하는 경로


  * Absolute Path

      File System을 Root로 두고 출발하는 경로


  * BufferedReader

      InputStream이나 Reader에 있는 read()는 한 binary씩 int형으로 반환되는 반면

      BufferedReader에 있는 readLine()은 해당 Data에서 한 줄씩 읽어들인다.(Scanning)

'Java > Theory' 카테고리의 다른 글

[Java/Theory]22. Thread  (0) 2016.05.31
[Java/Theory]21. Maker Interface  (0) 2016.05.31
[Java/Theory]20. IO  (0) 2016.05.31
[Java/Theory]19. interface기반, Inner class, instanceof  (0) 2016.05.31
[Java/Theory]18. Exception Handling  (0) 2016.05.31
[Java/Theory]17. AutoBoxing, Unboxing  (0) 2016.05.31

+ Recent posts

티스토리 툴바