2017년 4월 25일 화요일

중복제거 stream api, forkjoin, for문

소스:

https://github.com/julyinsung/thisandthat/tree/master/src/main/java/parallel/example

참고:

http://starplatina.tistory.com/entry/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%8A%B8%EB%A6%BC-API
http://starplatina.tistory.com/entry/Java-8-Stream-API-PART-2

환경:

gradle, java1.8

개요:

List의 단어 중복제거를 위해 stream, forkjoin, for문을 이용하여 구현.
List 사이즈는 2,000,000개이고 성능 평가(너무 궁금해서..).

설명:

  • 소스링크를 따라가면 3개의 클래스가 존재한다.
ForkJoinSample.java: ForkJoin이용. ForkJoin 게시글 참조
NormalSample.java: For문 이용
StreamSample.java: Stream API이용

  • 테스트는 test폴더의 각 테스트 코드 실행. \test\java\parallel\example
For문과 ForkJoin은 For문이 약간 우세, Stream API는 젤 느림. 
1.079s(For문) 
1.087s(ForkJoin) 
1.154s(Stream API)

  • 가독성 면으로 볼때는 Stream API가 우세.
List result = 
    list.parallelStream()
     .distinct()
     .collect(Collectors.toList());











ForkJoin

소스:

환경:

gradle, java1.8

개요:

ForkJoin라이브러리를 사용한 예제 구현.

설명:


1. 통상적인 예제는 int 배열의 숫자를 sum하는 것이나 여기서는 String List에서 다른 문장이 있는지 없는지를 체크(다른 아이디가 있는지를 체크)하는 예제로 수정.  

2. 사용법은 RecursiveTask<V>를 상속받아서 compute()를 구현한다.
compute()메소드의 구조는 설정한 SEQUENTIAL_THRESHOLD 이하인 경우는 로직을 수행하고 넘으면 다시 재귀호출을 하고 결과를 리턴한다.
public class ForkJoinSample extends RecursiveTask {

 static final int SEQUENTIAL_THRESHOLD = 500000; // 충분히 작은 단위는 여기서 5로 정했다.
             // 정하기 나름.


 public ForkJoinSample(List arr, int lo, int hi) {
    ....
 }

 @Override
 protected Boolean compute() {
  if (high - low <= SEQUENTIAL_THRESHOLD) { // 충분히 작은 배열 구간이면 값을 계산해 리턴한다.
   boolean result = true;

     // 수행로직...

   return result;

  } else {
   // 배열이 기준보다 크다면 divede and conquer방식으로 적당히 둘이상의 객체로 나누고,
   // 현재 쓰레드에서 처리할 객체는 compute를 호출해 값을 계산하고, fork할 객체는 join하여 값을 기다린후
   // 얻는다.
   int mid = low + (high - low) / 2;

   ForkJoinSample left = new ForkJoinSample(array, low, mid);
   ForkJoinSample right = new ForkJoinSample(array, mid, high);
   left.fork();
   Boolean rightAns = right.compute();
   Boolean leftAns = left.join();

   if (rightAns && leftAns) {
    return true;
   } else {
    return false;
   }
  }
 }
3. pool의 갯수는 commonPool()을 이용하여 자동으로 설정할수 있고 ForkJoinPool생성시 갯수를 지정 할 수 있다.
static Boolean read(List readAllLines) {
  // ForkJoinPool의 시작전과 후의 thread pool size를 비교한다.
  int beforeSize = ForkJoinPool.commonPool().getPoolSize();
  System.out.println("ForkJoin commonPool beforeSize=" + beforeSize);

  // common pool: 자동으로 pool갯수를 정해준다.
  boolean result = ForkJoinPool.commonPool().invoke(
    new ForkJoinSample(readAllLines, 0, readAllLines.size()));

  // custom pool: pool 갯수를 임의로 정할 수 있다.
  // ForkJoinPool myPool = new ForkJoinPool(3);
  // boolean result = myPool.invoke(new ForkJoinSample(readAllLines, 0,
  // readAllLines.size()));

  int afterSize = ForkJoinPool.commonPool().getPoolSize();
  System.out.println("ForkJoin commonPool afterSize=" + afterSize);
  return result;
 }



2017년 4월 24일 월요일

Spring Boot RestAPI

소스: 

https://github.com/julyinsung/springboot/tree/master/restapi-sample

환경:

spring boot, gradle 1.8, web

개요:

Spring Boot를 이용하여 Rest서버 연습.
WAR파일로 배포.


1. RestAPI 서버 연습

기존과 다른것은 Controlller 클래스에 @RestController 어노테이션을 사용한다.

@RestController
public class RestSampleController {
 
 @RequestMapping("/")
 public FileInfo RestTest(HttpServletRequest request){
  Files f = new JoinFile();
  
  String filePath = null;
  try {
   filePath = new ClassPathResource("CC01_IF20170131_0002_REQ").getFile().getPath();
  } catch (IOException e1) {
   e1.printStackTrace();
  }
  
  f.processFile(filePath);
  return f.getFileInfo();
 }
}

2. WAR파일 배포

  • build.gradle 파일에 plugin을 설정한다.
// war 설정

apply plugin: 'war'



// war 설정

war {

 baseName = 'ROOT'

}


  • 배포실행은 Gradle Tasks화면에서 build > war에 마우스 오른클릭후 실행 한다.

       생성된 WAR 파일은 프로젝트명\build\libs 폴더에 위치한다.








2017년 4월 20일 목요일

Spring Boot Batch

소스:

https://github.com/julyinsung/springboot/tree/master/spring-batch-sample

환경:

batch, h2, gradle

개요:

spring.io(https://spring.io/guides/gs/batch-processing/)에서 제공하는 예제를 이용하여 테스트. 

그밖에.. 

다른게 있다면 DB는 h2(http://www.h2database.com/html/main.html)로 변경

h2는 웹브라우저로 확인이 가능하므로 편의성때문에 변경해 봄.
그냥 웹브라우저로 확인은 불가하고 패키지 설치후 가능

build.gradle에 h2추가
dependencies {
 compile('org.springframework.boot:spring-boot-starter-batch')
 runtime('com.h2database:h2')
 testCompile('org.springframework.boot:spring-boot-starter-test')
}