[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/CodingPractice]04. CodingPractice04



소켓통신 1:1 채팅


Guest.java

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
package com.tcp.chat.client;
 
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
 
import com.tcp.chat.util.Receiver;
import com.tcp.chat.util.Sender;
 
public class Guest extends Thread {
 
    private Socket socket;
    private Sender sender;
    private Receiver receiver;
 
    /// Constructor
    public Guest(String host, int port, String name, Scanner scanner) throws IOException{
        super();
        this.socket = new Socket(host, port);
        this.sender = new Sender(this.socket, name, scanner);
        this.receiver = new Receiver(this.socket);
    }
    
    @Override
    public void run() {
        sender.start();
        receiver.start();
    }
 
    public static void main(String[] args) throws IOException {
        
        String host = "localhost";
        int port = 8080;
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("채팅할 아이디를 입력하세요.");
        String name = scanner.nextLine();
        
        Guest guest = new Guest(host, port, name, scanner);
        System.out.println("채팅방에 접속함. 호스트 IPv4 : " + host + ". \"exit\" 입력시 종료함. ");
        
        guest.start();
        
    }
}
cs


ChatSocket.java

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
package com.tcp.chat.server;
 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
 
import com.tcp.chat.util.Receiver;
import com.tcp.chat.util.Sender;
 
public class ChatSocket extends Thread {
 
    private Socket socket;
    private Sender sender;
    private Receiver receiver;
 
    // / Constructor
    public ChatSocket(Socket socket, String name, Scanner scanner) throws IOException {
        super();
        this.socket = socket;
        this.receiver = new Receiver(this.socket);
        this.sender = new Sender(this.socket, name, scanner);
        System.out.println("게스트가 접속함. 게스트 IPv4 : " + socket.getLocalAddress());
    }
 
    @Override
    public void run() {
        sender.start();
        receiver.start();
    }
    
    public static void main(String args[]) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        
        System.out.println("1:1 채팅방 만듬. \"exit\"입력시 종료함. 채팅할 아이디를 입력하세요.");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        
        ChatSocket tcpIpSocket = new ChatSocket(serverSocket.accept(), name, scanner);
        tcpIpSocket.start();
        serverSocket.close();
    }
 
}
cs


Receiver.java

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
package com.tcp.chat.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import com.tcp.chat.util.Receiver;
import com.tcp.chat.util.Sender;
public class ChatSocket extends Thread {
    private Socket socket;
    private Sender sender;
    private Receiver receiver;
    // / Constructor
    public ChatSocket(Socket socket, String name, Scanner scanner) throws IOException {
        super();
        this.socket = socket;
        this.receiver = new Receiver(this.socket);
        this.sender = new Sender(this.socket, name, scanner);
        System.out.println("게스트가 접속함. 게스트 IPv4 : " + socket.getLocalAddress());
    }
    @Override
    public void run() {
        sender.start();
        receiver.start();
    }
    
    public static void main(String args[]) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        
        System.out.println("1:1 채팅방 만듬. \"exit\"입력시 종료함. 채팅할 아이디를 입력하세요.");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        
        ChatSocket tcpIpSocket = new ChatSocket(serverSocket.accept(), name, scanner);
        tcpIpSocket.start();
        serverSocket.close();
    }
}
cs


Sender.java

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
package com.tcp.chat.util;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
 
public class Sender extends Thread{
    private PrintWriter printWriter;
    private Scanner scanner;
    private String chatToReceiver;
    private String senderName;
 
    /// Constructor
    public Sender(Socket socket, String senderName, Scanner scanner) throws IOException{
        super();
        this.printWriter = new PrintWriter(socket.getOutputStream());
        this.scanner = scanner;
        this.senderName = senderName;
    }
    
    public void closeAll() throws IOException{
        printWriter.close();
        scanner.close();
    }
    
    public void sendMessage(String message){
        printWriter.println("[ "+ senderName +" ] : " + message);
        System.out.println("[ "+ senderName +" ] : " + message);
        printWriter.flush();
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            while ((chatToReceiver = scanner.nextLine()) != null) {
                
                if (chatToReceiver.equals("exit")) {
                    break;
                }
                sendMessage(chatToReceiver);
            }
            closeAll();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}
cs


[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/CodingPractice]03. CodingPractice03


그룹 채팅.


Host.java

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
package com.chat.server;
 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
import com.chat.util.BroadCast;
import com.chat.util.GuestVO;
 
public class Host extends Thread {
    
    private ServerSocket serverSocket;
    private Socket       socket;
    private List<GuestVO>  guests;
    private int          port;
    
    public Host(int port) throws IOException  {
        super();
        this.port = port;
        this.serverSocket = new ServerSocket(this.port);
        guests = new ArrayList<GuestVO>();
        Collections.synchronizedList(guests);
    }
    
    @Override
    public void run(){
        System.out.println("채팅방을 켰음. 게스트들을 대기중... ");
        try {
            while(true){
                BroadCast broadCast = new BroadCast(serverSocket.accept(), this.guests);
                broadCast.start();
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
 
    public static void main(String args[]) throws IOException{
        new Host(8080).start();
    }
    
    
 
}
 
cs


BroadCast.java

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
52
53
54
55
56
57
58
59
60
61
62
63
package com.chat.util;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;
 
public class BroadCast extends Thread {
    
    private BufferedReader bufferedReader;
    private PrintWriter printWriter;
    private String chatFromReceiver;
    private List<GuestVO> guests;
    
    /// Constructor
    public BroadCast(Socket socket, List<GuestVO> guests) throws IOException{
        super();
        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        printWriter = new PrintWriter(socket.getOutputStream());
        this.guests = guests;
    }
    
    public void closeAll() throws IOException{
        bufferedReader.close();
        printWriter.close();
    }
    
    public void sendToAll(String message){
        for(GuestVO guest: guests){
            guest.getPrintWriter().println(message);
            guest.getPrintWriter().flush();
        }
    }
    
    @Override
    public void run() {
        GuestVO guest = null;
        // TODO Auto-generated method stub
        try {
            
            guest = new GuestVO(printWriter, bufferedReader.readLine());
            System.out.println("\"" + guest.getName() + "\"님이 접속함.");
            guests.add(guest);
            sendToAll("\"" + guest.getName() + "\" 님이 접속함.");
            
            while ((chatFromReceiver = bufferedReader.readLine()) != null){
                System.out.println("[ "+ guest.getName() +" ] : "+ chatFromReceiver);
                sendToAll("[ "+ guest.getName() +" ] : "+ chatFromReceiver);
            }
            closeAll();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally{
            System.out.println("\"" + guest.getName() + "\"님이 나감.");
            sendToAll("\"" + guest.getName() + "\"님이 나감.");
            guests.remove(guest);
        }
    }
}
 
cs


GuestVO.java

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 com.chat.util;
 
import java.io.PrintWriter;
 
public class GuestVO {
    
    private PrintWriter printWriter;
    private String name;
    
    public GuestVO(PrintWriter printWriter, String name) {
        super();
        this.printWriter = printWriter;
        this.name = name;
    }
 
    public PrintWriter getPrintWriter() {
        return printWriter;
    }
 
    public void setPrintWriter(PrintWriter printWriter) {
        this.printWriter = printWriter;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
    
    
}
 
cs


Guest.java

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
package com.chat.client;
 
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
 
import com.chat.util.Receiver;
import com.chat.util.Sender;
 
public class Guest extends Thread {
    
    private Socket socket;
    private Sender sender;
    private Receiver receiver;
    private Scanner scanner;
 
    /// Constructor
    public Guest(String iPv4, int port) throws IOException {
        this.socket = new Socket(iPv4, port);
        this.scanner = new Scanner(System.in);
        this.sender = new Sender(socket, scanner);
        this.receiver = new Receiver(socket);
    }
 
    @Override
    public void run() {
        sender.start();
        receiver.start();
    }
    
    public static void main(String[] args) throws IOException{
        Guest guest = new Guest("localhost"8080);
        guest.start();
    }
    
}
 
cs


Receiver.java

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
package com.chat.util;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
 
public class Receiver extends Thread {
    private BufferedReader bufferedReader;
    private String chatFromReceiver;
 
    /// Constructor
    public Receiver(Socket socket) throws IOException{
        super();
        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }
    
    public void closeAll() throws IOException{
        bufferedReader.close();
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            while ((chatFromReceiver = bufferedReader.readLine()) != null){
                System.out.println(chatFromReceiver);
            }
            closeAll();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}
 
cs


Sender.java

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
package com.chat.util;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
 
public class Sender extends Thread{
    private PrintWriter printWriter;
    private Scanner scanner;
    private String chatToReceiver;
 
    /// Constructor
    public Sender(Socket socket, Scanner scanner) throws IOException{
        super();
        this.printWriter = new PrintWriter(socket.getOutputStream());
        this.scanner = scanner;
    }
    
    public void closeAll() throws IOException{
        printWriter.close();
        scanner.close();
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        
        System.out.println("서버에 접속함. 이름 입력.");
        printWriter.println(scanner.nextLine());
        printWriter.flush();
        
        try {
            while ((chatToReceiver = scanner.nextLine()) != null) {
                
                if (chatToReceiver.equals("exit")) {
                    break;
                }
                printWriter.println(chatToReceiver);
                printWriter.flush();
            }
            closeAll();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}
 
cs


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


http://hyeonstorage.tistory.com/252

http://hyeonstorage.tistory.com/254

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
 
public class CodingPractice02 {
 
    public static boolean isOverlapped(Circle c1, Circle c2){
        double sumOfR = c1.getR() + c2.getR();
        double distance = Math.sqrt(Math.pow(c1.getX()-c2.getX(),2+ Math.pow(c1.getY() - c2.getY(), 2));
        
        if(distance < sumOfR){
            return true;
        }else{
            return false;
        }
        
    }
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Scanner scan = new Scanner(System.in);
        int theNumberOfCircle=-1;
        
        // set the number of circles
        while(theNumberOfCircle < 0){            
            System.out.println("Please input the number of circles.");
            theNumberOfCircle = scan.nextInt();
            
            if(theNumberOfCircle<0){
                System.out.print("Worng value. ");
            }
        }
        
        List<Circle> circles = new ArrayList<Circle>(theNumberOfCircle);
        List<Integer> circlesId = new ArrayList<Integer>(theNumberOfCircle);
        
        // input circles
        for(int i = 0 ; i < theNumberOfCircle ; i++){
            
            Circle tempCircle = new Circle(scan.nextInt(), scan.nextDouble(), scan.nextDouble(), scan.nextDouble());
            
            // validation check
            // range of circle
            if(
                    (1 > tempCircle.getId() || tempCircle.getId() > 300||
                    (-10000 > tempCircle.getX() || tempCircle.getX() > 10000||
                    (-10000 > tempCircle.getY() | tempCircle.getY() > 10000||
                    (0 >= tempCircle.getR() || tempCircle.getR() > 10000)
              ){
                System.out.println("Worng value");
                i--;
                continue;
            }else if(i > 0){
                // ID duplication check
                if(circlesId.contains(tempCircle.getId())){
                    System.out.println("Worng value");
                    i--;
                    continue;
                }
            }
            
            circles.add(tempCircle);
            circlesId.add(tempCircle.getId());
            
        }
        
        
        // printing overlapped circles
        for(int i = 0 ; i < circles.size() ; i ++){
            for(int j = i ; j < circles.size() ; j++){
                if(i==j){
                    continue;
                }else{
                    if(isOverlapped(circles.get(i), circles.get(j))){
                        System.out.println(circles.get(i).getId() + ", " + circles.get(j).getId());                                            
                    }
                }
            }
        }
        
        
        
    }
 
}
 
class Circle{
    
    private int    id;
    private double x;
    private double y;
    private double r;
    
    
    public Circle() {
        super();
    }
 
    public Circle(int id, double x, double y, double r) {
        super();
        this.id = id;
        this.x = x;
        this.y = y;
        this.r = r;
    }
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public double getX() {
        return x;
    }
    public void setX(double x) {
        this.x = x;
    }
    public double getY() {
        return y;
    }
    public void setY(double y) {
        this.y = y;
    }
    public double getR() {
        return r;
    }
    public void setR(double r) {
        this.r = r;
    }
    
}
cs


Click here to Github


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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class CodingPractice01 {
    
    // 주어진 정수를 뒤집어서 출력
    // Ex : 46312 => 21364
    public static int getReversedInteger(int val){
        StringBuffer returnVal = new StringBuffer();
        int length = String.valueOf(val).length();
        
        for(int i = 0 ; i < length ; i ++){
            returnVal.append(val%10);
            val /= 10;
        }
        
        return Integer.parseInt(returnVal.toString());
    }
    
    // 배열을 오름차순으로 정렬하고 중간값 출력
    // 입력받은 수들의 개수가 짝수면 두 개의 중간값의 평균을 출력
    // Ex : 10, 2, 101, 90 => 50
    public static double getMedian(int[] val){
        int indexMin, temp;
        
        // Selection sort
        for(int i = 0 ; i < val.length; i++){
            indexMin = 0;
            for(int j = i; j < val.length ; j++){
                if(val[indexMin] > val[j]){
                    indexMin = j;
                }
            }
            temp = val[indexMin];
            val[indexMin] = val[i];
            val[i] = temp;
        }
        
        if(val.length % 2==0){
            return (val[val.length/2+ val[val.length/2+1])/2;
        }else{
            return val[val.length/2+1];
        }
        
    }    
    
    // 해당 순번의 피보나치의 값 출력
    // Ex : 2 => 1, 8 => 21
    // no recursive
    public static int getFibonacciNumber(int val){
        
        int prePre = 0;
        int pre = 1;
        int in  = 0;
        
        if(val <= 0){
            return prePre;
        }else if(val == 1){
            return pre;
        }else{
            for(int i = 0 ; i < val-1 ; i ++){
                in = prePre + pre;
                prePre = pre;
                pre = in;
            }
            return pre;
        }
        
    }
    
    public static void main(String args[]){
        System.out.println(getReversedInteger(46312));
        // 21364
        
        int arrayInt[] = {10210190};
        System.out.println(getMedian(arrayInt));
        // 50.0
        
        System.out.println(getFibonacciNumber(8));
        // 21
        
    }
 
}
cs


+ Recent posts

티스토리 툴바