モジュール java.base
パッケージ java.util.concurrent

クラスCountedCompleter<T>

java.lang.Object
java.util.concurrent.ForkJoinTask<T>
java.util.concurrent.CountedCompleter<T>
すべての実装されたインタフェース:
Serializable, Future<T>

public abstract class CountedCompleter<T> extends ForkJoinTask<T>
トリガーされた時点で保留中のアクションが残っていない場合に実行される完了アクションを含むForkJoinTaskです。 CountedCompleterは、一般にサブタスクの停止やブロックが発生した場合は他の形式のForkJoinTaskより堅牢ですが、直感的にプログラミングしにくくなります。 CountedCompleterの使用方法は他の完了ベースのコンポーネント(CompletionHandlerなど)と同様ですが、完了アクションonCompletion(CountedCompleter)をトリガーするためには、1つではなく複数の保留完了が必要になることがあります。 別の方法で初期化された場合を除き、保留カウントはゼロから始まりますが、setPendingCount(int)addToPendingCount(int)およびcompareAndSetPendingCount(int, int)メソッドを使用して(原子的に)変更できます。 tryComplete()を呼び出したときに、保留アクションのカウントがゼロでない場合は、値が減らされます。それ以外の場合は、完了アクションが実行され、このコンプリータ自体がコンプリータを持っている場合はそのコンプリータで処理が続行されます。 PhaserSemaphoreなどの関連する同期化コンポーネントと同様に、これらのメソッドは内部のカウントにしか影響を与えず、それ以上の内部登録を確立しません。 特に、保留タスクの識別情報は保持されません。 次に示すように、必要に応じて保留タスクまたはそれらの結果の一部または全部を記録するサブクラスを作成できます。 次に示すように、完了のトラバースのカスタマイズをサポートするユーティリティ・メソッドも提供されます。 ただし、CountedCompleterは基本的な同期化メカニズムのみを提供するため、一連の関連する用途に適したリンク、フィールドおよび追加のサポート・メソッドを保持するその他の抽象サブクラスを作成するときに便利な場合があります。

具象CountedCompleterクラスは、ほとんどのケースで(次に示すように)復帰する前にtryComplete()を1回呼び出すcompute()メソッドを定義する必要があります。 このクラスでは、オプションで、正常な完了時にアクションを実行するonCompletion(CountedCompleter)メソッドと、例外の発生時にアクションを実行するonExceptionalCompletion(Throwable, CountedCompleter)メソッドをオーバーライドすることもできます。

ほとんどの場合、CountedCompleterは結果を生成しません。通常はCountedCompleter<Void>として宣言され、結果値として常にnullを返します。 それ以外の場合は、getRawResult()メソッドをオーバーライドして、join()、invoke()および関連メソッドから結果を提供するようにしてください。 一般に、このメソッドは完了時の結果を保持するCountedCompleterオブジェクトのフィールド(または1つ以上のフィールドの関数)の値を返す必要があります。 setRawResult(T)メソッドは、デフォルトではCountedCompleterに何の影響も与えません。 適用可能なケースはほとんどありませんが、このメソッドをオーバーライドして、結果データを持つ他のオブジェクトやフィールドを保持することも可能です。

それ自体ではコンプリータを持たない(つまり、getCompleter()nullを返す)CountedCompleterは、この追加機能を含む通常のForkJoinTaskとして使用できます。 ただし、別のコンプリータを持つコンプリータは、他の計算の内部ヘルパーとしてのみ機能するため、(ForkJoinTask.isDone()などのメソッドで報告される)それ自体のタスク・ステータスは不定です。このステータスは、complete(T)ForkJoinTask.cancel(boolean)ForkJoinTask.completeExceptionally(Throwable)の明示的な呼出し時、またはcomputeメソッドの例外完了時にのみ変更されます。 例外完了時に、タスクのコンプリータ(およびそのコンプリータ、以下同様)が存在し、まだ完了していない場合は、それらに例外が中継されます。 同様に、内部のCountedCompleterを取り消しても、そのコンプリータに対するローカルの効果しかないため、多くの場合有効ではありません。

使用例。

並列の再帰的分解。 CountedCompleterは、RecursiveActionで使用されるものと同様のツリーに配置できます。ただし、それらの設定では通常、異なる方法で構築が行われます。 この場合、各タスクのコンプリータは、計算ツリーではタスクの親になります。 必要な登録作業がやや多くなりますが、配列またはコレクションの各要素に時間のかかる(それ以上分割できない)オペレーションを適用する場合(特に、入出力などの固有の差違またはガベージ・コレクションなどの補助効果のいずれかが原因で、そのオペレーションの完了にかかる時間が要素によって大幅に異なる場合)、CountedCompleterはより適切な方法である可能性があります。 CountedCompletersは独自の継続を提供するため、他のタスクはそれらを実行するための待機をブロックする必要はありません。

例えば、ここでは2分法の再帰的分解を使用して作業を1つの部分(リーフ・タスク)に分割するユーティリティ・メソッドの初期バージョンがあります。 作業が個別の呼出しに分割されている場合でも、通常はリーフ・タスクを直接フォークするより、スレッド間通信が減少し、負荷分散が向上するツリーベースの手法をお薦めします。 再帰的なケースでは、終了するサブタスクの各ペアの2番目のペアが、親(結果の組み合わせが実行されないため、メソッドonCompletionのデフォルトのno-op実装はオーバーライドされません)の完了をトリガーします。 ユーティリティ・メソッドは、ルート・タスクを設定し、それを(ここでは、暗黙のうちにForkJoinPool.commonPool())を呼び出します。 保留中のカウントを子タスクの数に常に設定し、戻す直前に tryComplete()を呼び出すことは、簡単で信頼性の高い(最適ではない)です。

 
 public static <E> void forEach(E[] array, Consumer<E> action) {
   class Task extends CountedCompleter<Void> {
     final int lo, hi;
     Task(Task parent, int lo, int hi) {
       super(parent); this.lo = lo; this.hi = hi;
     }

     public void compute() {
       if (hi - lo >= 2) {
         int mid = (lo + hi) >>> 1;
         // must set pending count before fork
         setPendingCount(2);
         new Task(this, mid, hi).fork(); // right child
         new Task(this, lo, mid).fork(); // left child
       }
       else if (hi > lo)
         action.accept(array[lo]);
       tryComplete();
     }
   }
   new Task(null, 0, array.length).invoke();
 }
再帰的なケースでは、タスクがその右側のタスクをフォークした後で何も実行しないため、復帰する前にその左側のタスクを直接呼び出すことができる点に気づくことで、この設計を改良できます。 (これは末尾再帰の削除に似ています。) また、タスクの最後のアクションがサブタスク("テール・コール")をforkまたは呼び出しする場合は、 tryComplete()への呼び出しを最適化して、保留中のカウントを"1つずつオフ"のように見せかけることができます。
 
     public void compute() {
       if (hi - lo >= 2) {
         int mid = (lo + hi) >>> 1;
         setPendingCount(1); // looks off by one, but correct!
         new Task(this, mid, hi).fork(); // right child
         new Task(this, lo, mid).compute(); // direct invoke
       } else {
         if (hi > lo)
           action.accept(array[lo]);
         tryComplete();
       }
     }
さらなる最適化として、左のタスクが存在する必要はないことに注意してください。 新しいタスクを作成する代わりに、元のタスクを引き続き使用して、各フォークの保留カウントを追加することができます。 また、このツリー内のタスクはonCompletion(CountedCompleter)メソッドを実装していないため、tryCompletepropagateCompletion()に置き換えることができます。
 
     public void compute() {
       int n = hi - lo;
       for (; n >= 2; n /= 2) {
         addToPendingCount(1);
         new Task(this, lo + n/2, lo + n).fork();
       }
       if (n > 0)
         action.accept(array[lo]);
       propagateCompletion();
     }
ペンディング・カウントをあらかじめ計算することができれば、それらはコンストラクタで確立できます:
 
 public static <E> void forEach(E[] array, Consumer<E> action) {
   class Task extends CountedCompleter<Void> {
     final int lo, hi;
     Task(Task parent, int lo, int hi) {
       super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
       this.lo = lo; this.hi = hi;
     }

     public void compute() {
       for (int n = hi - lo; n >= 2; n /= 2)
         new Task(this, lo + n/2, lo + n).fork();
       action.accept(array[lo]);
       propagateCompletion();
     }
   }
   if (array.length > 0)
     new Task(null, 0, array.length).invoke();
 }
このようなクラスの追加の最適化では、リーフ・ステップのクラスを特化し、反復ごとに2つではなく4つに分割し、常に単一の要素に細分するのではなく、適応しきい値を使用することがあります。

検索 CountedCompleterのツリーでは、データ構造の様々な部分に含まれる値またはプロパティを検索し、結果が見つかった場合はただちにAtomicReferenceに結果を報告できます。 他のタスクはその結果をポーリングして、不要な作業を回避できます。 (さらに、他のタスクを取り消すこともできますが、通常は結果が設定されたことをそれらに通知し、その場合は後続の処理を省略させるのがより簡単で効率的です。) 完全なパーティション化を使用する配列を使って再度説明します(この場合も、実際には、リーフ・タスクはほとんど常に複数の要素を処理します)。

 
 class Searcher<E> extends CountedCompleter<E> {
   final E[] array; final AtomicReference<E> result; final int lo, hi;
   Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
     super(p);
     this.array = array; this.result = result; this.lo = lo; this.hi = hi;
   }
   public E getRawResult() { return result.get(); }
   public void compute() { // similar to ForEach version 3
     int l = lo, h = hi;
     while (result.get() == null && h >= l) {
       if (h - l >= 2) {
         int mid = (l + h) >>> 1;
         addToPendingCount(1);
         new Searcher(this, array, result, mid, h).fork();
         h = mid;
       }
       else {
         E x = array[l];
         if (matches(x) && result.compareAndSet(null, x))
           quietlyCompleteRoot(); // root task is now joinable
         break;
       }
     }
     tryComplete(); // normally complete whether or not found
   }
   boolean matches(E e) { ... } // return true if found

   public static <E> E search(E[] array) {
       return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
   }
 }
この例では、タスクがcompareAndSet以外の他の効果を持たない他のものと同様に、tryCompleteの後続の無条件呼び出しは、ルート・タスクが完了した後に補完を管理するためにそれ以上の簿記が必要ないため条件(if (result.get() == null) tryComplete();)付きで行うことができます。

サブタスクの記録。 複数のサブタスクの結果を結合するCountedCompleterタスクは、通常、onCompletion(CountedCompleter)メソッドでこれらの結果にアクセスする必要があります。 次の(マッピングとリダクションの型がすべてEである簡易形式のマップ・リデュースを実行する)クラスに示すように、分割統治型の設計でこれを行う方法の1つは、各サブタスクにその兄弟を記録させ、onCompletionメソッドでそれにアクセスできるようにすることです。 この手法は、左と右の結果を結合する順序が問題にならないようなリダクションに適用されます。順序付けされたリダクションでは、左と右を明示的に指定する必要があります。 前の例に示した他の合理化方法のバリアントを適用することもできます。

 
 class MyMapper<E> { E apply(E v) {  ...  } }
 class MyReducer<E> { E apply(E x, E y) {  ...  } }
 class MapReducer<E> extends CountedCompleter<E> {
   final E[] array; final MyMapper<E> mapper;
   final MyReducer<E> reducer; final int lo, hi;
   MapReducer<E> sibling;
   E result;
   MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
              MyReducer<E> reducer, int lo, int hi) {
     super(p);
     this.array = array; this.mapper = mapper;
     this.reducer = reducer; this.lo = lo; this.hi = hi;
   }
   public void compute() {
     if (hi - lo >= 2) {
       int mid = (lo + hi) >>> 1;
       MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
       MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
       left.sibling = right;
       right.sibling = left;
       setPendingCount(1); // only right is pending
       right.fork();
       left.compute();     // directly execute left
     }
     else {
       if (hi > lo)
           result = mapper.apply(array[lo]);
       tryComplete();
     }
   }
   public void onCompletion(CountedCompleter<?> caller) {
     if (caller != this) {
       MapReducer<E> child = (MapReducer<E>)caller;
       MapReducer<E> sib = child.sibling;
       if (sib == null || sib.result == null)
         result = child.result;
       else
         result = reducer.apply(child.result, sib.result);
     }
   }
   public E getRawResult() { return result; }

   public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
     return new MapReducer<E>(null, array, mapper, reducer,
                              0, array.length).invoke();
   }
 }
ここで、onCompletionメソッドは結果を結合する多くの完了設計に共通する形式を取っています。 このコールバック形式のメソッドは、保留カウントがゼロである(またはゼロになる)2つの異なるコンテキストのいずれかで、タスクごとに1回トリガーされます。つまり、(1) tryCompleteの呼出し時にその保留カウントがゼロである場合は、そのタスク自体によってトリガーされ、(2)そのサブタスクのいずれかが完了し、保留カウントをゼロに減らしたときは、そのサブタスクによってトリガーされます。 caller引数はケースを区別します。 ほとんどの場合、呼出し側がthisであれば、アクションは不要です。 それ以外の場合、caller引数は結合される値(または他の値へのリンク、あるいはその両方)を提供するために(通常はキャストを介して)使用されます。 保留カウントが適切に使用されていれば、onCompletion内のアクションはタスクおよびそのサブタスクの完了時に(1回)発生します。 このタスクまたは他の完了したタスクのフィールドへのアクセスのスレッド安全性を確保するために、このメソッド内に同期化を追加する必要はありません。

完了のトラバース onCompletionを使用して完了を処理することが不適当または不都合である場合は、firstComplete()およびnextComplete()メソッドを使用してカスタム・トラバースを作成できます。 たとえば、3番目のForEachの例の形式で右側のタスクを分割するのみのMapReducerを定義するには、使い果たされていないサブタスクのリンクに沿って完了を協調的にリデュースする必要があり、次のように行うことができます。

 
 class MapReducer<E> extends CountedCompleter<E> { // version 2
   final E[] array; final MyMapper<E> mapper;
   final MyReducer<E> reducer; final int lo, hi;
   MapReducer<E> forks, next; // record subtask forks in list
   E result;
   MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
              MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
     super(p);
     this.array = array; this.mapper = mapper;
     this.reducer = reducer; this.lo = lo; this.hi = hi;
     this.next = next;
   }
   public void compute() {
     int l = lo, h = hi;
     while (h - l >= 2) {
       int mid = (l + h) >>> 1;
       addToPendingCount(1);
       (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
       h = mid;
     }
     if (h > l)
       result = mapper.apply(array[l]);
     // process completions by reducing along and advancing subtask links
     for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
       for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
         t.result = reducer.apply(t.result, s.result);
     }
   }
   public E getRawResult() { return result; }

   public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
     return new MapReducer<E>(null, array, mapper, reducer,
                              0, array.length, null).invoke();
   }
 }

トリガー。 CountedCompleterの中には、それ自体はフォークされないが、かわりに他の設計の構成要素の一部として機能するものがあります。これには、1つ以上の非同期タスクの完了が別の非同期タスクをトリガーするCountedCompleterが含まれます。 次に例を示します。

 
 class HeaderBuilder extends CountedCompleter<...> { ... }
 class BodyBuilder extends CountedCompleter<...> { ... }
 class PacketSender extends CountedCompleter<...> {
   PacketSender(...) { super(null, 1); ... } // trigger on second completion
   public void compute() { } // never called
   public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
 }
 // sample use:
 PacketSender p = new PacketSender();
 new HeaderBuilder(p, ...).fork();
 new BodyBuilder(p, ...).fork();

導入されたバージョン:
1.8
関連項目:
  • コンストラクタの詳細

    • CountedCompleter

      protected CountedCompleter(CountedCompleter<?> completer, int initialPendingCount)
      指定されたコンプリータと初期保留カウントを使用して、新しいCountedCompleterを作成します。
      パラメータ:
      completer - このタスクのコンプリータ。存在しない場合はnull
      initialPendingCount - 初期の保留カウント
    • CountedCompleter

      protected CountedCompleter(CountedCompleter<?> completer)
      指定されたコンプリータと、保留カウントの初期値ゼロを使用して、新しいCountedCompleterを作成します。
      パラメータ:
      completer - このタスクのコンプリータ。存在しない場合はnull
    • CountedCompleter

      protected CountedCompleter()
      コンプリータを持たず、初期の保留カウントがゼロである新しいCountedCompleterを作成します。
  • メソッドの詳細

    • compute

      public abstract void compute()
      このタスクによって実行される主な計算です。
    • onCompletion

      public void onCompletion(CountedCompleter<?> caller)
      メソッドtryComplete()が呼び出されたときに保留カウントがゼロの場合、または無条件メソッドcomplete(T)が呼び出された場合、アクションを実行します。 デフォルトでは、このメソッドは何も行いません。 指定された呼出し側引数の識別情報を確認することで、ケースを区別できます。 thisと等しくない場合は、通常、結合する結果(または他の結果へのリンク、あるいはその両方)を含む可能性があるサブタスクです。
      パラメータ:
      caller - このメソッドを呼び出しているタスク(このタスク自体である場合もある)
    • onExceptionalCompletion

      public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller)
      メソッドForkJoinTask.completeExceptionally(Throwable)が呼び出されたかメソッドcompute()が例外をスローしたときに、このタスクがまだ正常に完了していない場合、アクションを実行します。 このメソッドに入ったときは、このタスクはForkJoinTask.isCompletedAbnormally() (異常な状態での完了)になります。 このメソッドの戻り値は、さらなる伝播を左右します。戻り値がtrueで、このタスクが完了していないコンプリータを持っている場合は、そのコンプリータもこのコンプリータと同じ例外で完了します。 このメソッドのデフォルト実装は、trueを返す以外何もしません。
      パラメータ:
      ex - 例外
      caller - このメソッドを呼び出しているタスク(このタスク自体である場合もある)
      戻り値:
      この例外をこのタスクのコンプリータ(存在する場合)に伝播する必要がある場合はtrue
    • getCompleter

      public final CountedCompleter<?> getCompleter()
      このタスクのコンストラクタで確立されたコンプリータがある場合はそれを返し、ない場合はnullを返します。
      戻り値:
      コンプリータ
    • getPendingCount

      public final int getPendingCount()
      現在の保留カウントを返します。
      戻り値:
      現在の保留カウント
    • setPendingCount

      public final void setPendingCount(int count)
      保留カウントを指定された値に設定します。
      パラメータ:
      count - カウント
    • addToPendingCount

      public final void addToPendingCount(int delta)
      指定された値を保留カウントに(原子的に)追加します。
      パラメータ:
      delta - 追加する値
    • compareAndSetPendingCount

      public final boolean compareAndSetPendingCount(int expected, int count)
      保留カウントが指定された予想値を現在保持している場合にのみ、保留カウントを指定されたカウントに(原子的に)設定します。
      パラメータ:
      expected - 予想値
      count - 新しい値
      戻り値:
      成功した場合はtrue
    • decrementPendingCountUnlessZero

      public final int decrementPendingCountUnlessZero()
      保留カウントがゼロ以外の場合に、それを(原子的に)減分します。
      戻り値:
      このメソッドに入ったときに保持される初期の(減分されていない)保留カウント
    • getRoot

      public final CountedCompleter<?> getRoot()
      現在の計算のルートを返します。つまり、このタスクにコンプリータがない場合はこのタスクを返し、それ以外の場合はそのコンプリータのルートを返します。
      戻り値:
      現在の計算のルート
    • tryComplete

      public final void tryComplete()
      保留カウントがゼロでない場合は、そのカウントを減らします。それ以外の場合は、onCompletion(CountedCompleter)を呼び出した後、このタスクのコンプリータが存在する場合は、同様にその実行を試み、存在しない場合は、このタスクを完了したものとしてマークします。
    • propagateCompletion

      public final void propagateCompletion()
      tryComplete()と同等ですが、完了パスに沿ってonCompletion(CountedCompleter)を呼び出しません。保留カウントがゼロ以外の場合は、カウントを減分します。そうでない場合は、同様にこのタスクのコンプリータを完了しようとし、コンプリータが存在しない場合はこのタスクを完了したものとしてマークします。 このメソッドは、計算内の各コンプリータに対してonCompletionを呼び出すことができない(または必要でない)場合に役立つことがあります。
    • complete

      public void complete(T rawResult)
      保留カウントに関係なく、onCompletion(CountedCompleter)を呼び出し、このタスクを完了したものとしてマークし、さらにこのタスクのコンプリータに対してtryComplete()をトリガーします(存在する場合)。 指定されたrawResultは、onCompletion(CountedCompleter)を呼び出すか、またはこのタスクを完了したものとしてマークする前に、setRawResult(T)への引数として使用されます。その値は、setRawResultをオーバーライドするクラスでのみ有効です。 このメソッドは保留カウントを変更しません。

      このメソッドは、複数のサブタスクの結果の(すべてではなく)いずれかが取得された直後に強制的に完了する場合に役立つことがあります。 しかし、 setRawResultがオーバーライドされない共通の(推奨)の場合、この効果はquietlyCompleteRoot()を使用するとより簡単に取得できます。

      オーバーライド:
      complete、クラス: ForkJoinTask<T>
      パラメータ:
      rawResult - 生の結果
    • firstComplete

      public final CountedCompleter<?> firstComplete()
      このタスクの保留カウントがゼロの場合は、このタスクを返します。それ以外の場合は、その保留カウントを減分し、nullを返します。 このメソッドは、完了トラバース・ループでnextComplete()とともに使用するように設計されています。
      戻り値:
      保留カウントがゼロだった場合はこのタスク。それ以外の場合はnull
    • nextComplete

      public final CountedCompleter<?> nextComplete()
      このタスクにコンプリータがない場合は、ForkJoinTask.quietlyComplete()を呼び出し、nullを返します。 または、コンプリータの保留カウントがゼロ以外の場合は、その保留カウントを減分し、nullを返します。 それ以外の場合は、コンプリータを返します。 このメソッドは、同種類のタスク階層に対する完了トラバース・ループの一部として使用できます。
       
       for (CountedCompleter<?> c = firstComplete();
            c != null;
            c = c.nextComplete()) {
         // ... process c ...
       }
      戻り値:
      コンプリータ。存在しない場合はnull
    • quietlyCompleteRoot

      public final void quietlyCompleteRoot()
      getRoot().quietlyComplete()と同等です。
    • helpComplete

      public final void helpComplete(int maxTasks)
      このタスクが完了していない場合に、このタスクがその完了パスに含まれる他の未処理タスクの処理を、指定された数を限度に試行します(そのようなタスクが存在することがわかっている場合)。
      パラメータ:
      maxTasks - 処理するタスクの最大数。 ゼロまたはそれより小さい場合、タスクは処理されない。
    • exec

      protected final boolean exec()
      CountedCompleterの実行規則を実装します。
      定義:
      exec、クラス: ForkJoinTask<T>
      戻り値:
      このタスクが正常に完了したことがわかっている場合はtrue
    • getRawResult

      public T getRawResult()
      計算の結果を返します。 デフォルトでは、Voidアクションに適したnullが返されますが、他の場合は、ほとんどの場合、完了時に結果を保持するフィールドまたはフィールドの関数を返す必要があります。
      定義:
      getRawResult、クラス: ForkJoinTask<T>
      戻り値:
      計算の結果
    • setRawResult

      protected void setRawResult(T t)
      結果を生成するCountedCompleterが結果データを保持するためにオプションで使用するメソッドです。 デフォルトでは、何もしません。 オーバーライドはお薦めしません。 ただし、このメソッドをオーバーライドして既存のオブジェクトまたはフィールドを更新する場合は、一般にこのメソッドをスレッド・セーフになるように定義する必要があります。
      定義:
      setRawResult、クラス: ForkJoinTask<T>
      パラメータ:
      t - 値