스레드 스케줄러Thread.yield, 스레드 우선순위에 의존하지 말자. 견고성과 이식성을 모두 해치는 행위이다.
스레드 우선순위는 프로그램의 서비스 품질을 높이는데 드물게 쓰일 수는 있지만 프로그램을 고치는 용도로 사용해서는 안된다.

• 정확성이나 성능이 운영체제 고유의 스레드 스케줄러에 따라 달라지는 프로그램일수록 다른 플랫폼에 이식하기 어렵다.

• 견고하고 이식성 좋은 프로그램을 작성하기 위해서 고려해야 할 것들

    ◦  실행 가능한 스레드의 평균 개수를 프로세서 수 보다 지나치게 많아지지 않도록 관리할 것

    ◦  즉 실행가능한 스레드 수를 가능한 적게 유지하는 것이 중요하다.


실행 가능한 스레드 수를 적게 유지하는 방법

• 실행 준비가 된 스레드들은 맡은 작업을 완료할 때 까지 계속 실행되도록 할 것

    ◦  단 실행 가능한 스레드 수 와 전체 스레드 수는 구분해야 한다. (대기 중인 스레드 = 실행 불가)

• 스레드는 당장 처리해야 할 작업이 없다면 실행 되어서는 안된다.

• 스레드는 Busy Waiting 상태가 되면 안된다.

    ◦  Busy Waiting 상태

-  스레드 스케줄러 환경의 변화에 취약하다. (이식성이 낮다)

-  프로세서에 부담을 주어 다른 작업이 실행의 기회를 박탈당한다. (성능이 낮다)

-  Busy Waiting이 발생하는 코드 예시 (작가평 : 끔찍한 코드이다!)

public class SlowCountDownLatch {
  private int count;

  public SlowCountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException(count + " < 0");
    this.count = count;
  }

  public void await() {
    while (true) {
      synchronized(this) { if (count == 0) return; }
    }
  }

  public synchronized void countDown() {
    if (count != 0) count--;
  }

}

Thread.yield 사용을 주의하라

• Thread.yield : 다른 스레드에게 실행을 양보하는 메서드

    ◦  실행 중인 스레드를 RUNNABLE (실행 대기) 상태로 바꾼다.

          -  스레드가 실행되었는데, 그 실행이 잠시동안 무의미한 경우가 있을 수 있다.

          -  이런 경우 스레드를 잠시 실행 대기 상태로 돌려놓으면 CPU의 자원의 소모를 방지할 수 있다.

          -  이 때 Thread.yield 메소드가 유용하게 사용될 수 있다.

• 특정 스레드가 다른 스레드에 비해 CPU 자원을 할당받지 못하는 경우에도 Thread.yield 사용은 지양하자

    ◦  증상이 호전될 수 있어도 여전히 이식성이 나쁘다

          -  JVM 종류에 따라 차이가 미미할수도, 악화될수도 있다.

• 차라리 어플리케이션 구조를 바꿔 동시에 실행 가능한 스레드 수를 줄이는 것이 좋다.


스레드 우선순위 조정에 주의하라

• 스레드 우선순위는 자바에서 이식성이 가장 나쁜 특성 중 하나이다.

    ◦  A 타입의 JVM 에서 1-2-3 의 순서로 실행되었다고 하더라도, B 타입의 JVM에서 동일한 순서로 실행되리라는 보장이 없다.

          -  A 타입에서 1-2-3 의 순서로 실행된 것이 B 타입의 JVM 에서는 3-1-2 의 순서로 실행될 수 있음

          -  즉 1-2-3 이 최적의 성능을 보장하는 우선순위 였다고 해도, 다른 JVM 에서 3-1-2 의 순서로 실행되어 버리면 다시 성능이 나빠진다.

• 특히 응답 불가 문제는 스레드 우선순위로 해결해선 안된다.

    ◦  진짜 원인을 찾아 수정하기 전까지 같은 문제가 반복해서 발생할 것이다.