Java

Java SE 9 の予習 その3

Java

Java SE 9 の予習 その3です。

今回のエントリーは JShell です。

JShell は多くの開発者から期待されておりネット上に情報があふれています。

特に「最新Java情報局」の連載記事は解りやすくお勧めです。

そこで今回のエントリーは「こんな使い方はしないだろう」という内容のものを書きます。

つまり、ただのお遊びです

でもネット上でこの情報を見ることができるのは此処だけかもしれませんよ。(^_^;

それだけ必要がない無駄な情報と言えます。

それでは過去のエントリーをまずご覧ください。

よく見かけるネタ IntegerCache 問題

Java ではよく知られている IntegerCache 問題です。

これは JVM オプションを設定することにより変更が可能です。

-XX:AutoBoxCacheMax=<size>

これを JShell で設定してうごかしてみたいと思いませんか?

思わない・・・ そう、普通は思いませんよね。

でも、私は天の邪鬼な人間なのでどうすればいいか必死になってググりました。

でもヒットせず twitter で泣きながらつぶやいたら「ジャバチョットデキル」優しい人達に救われました。

JShell は「Java SE 9のProject Kulla、JShellの動作とJShell API」の記事「JShellの動作」にあるように

JShell process と Java process のふたつの JVM が立ち上がっています。

つまり、JShell process からリモート JVM の Java process にコンパイルされたバイトコードを渡し実行した結果を返してもらっているようです。

だからリモート JVM に JVM オプションを設定しなければなりません。

まず、JShell を起動します。

a1

次に IntegerCache 問題のコードを入力していきます。

a2

ちゃんと false となっています。

これを true にするために下記の JVM オプションを JShell 起動コマンドに追加します。

-R-XX:AutoBoxCacheMax=128

a3

期待通りに true になってくれました。

次はプログラムから JShell API を使ってみようと思います。

今回のようにリモート JVM オプションを設定したり、コンパイルオプションを設定してみました。

またプログラムから JShell API を使うときに思い込みから「あれれ?」となったことも。

ちょっと今日は遅くなってしまったので次回にそれらは書く予定です。

それでは G’Night! Zzz…

Java SE 9 の予習

Java SE 9 の予習 その2

Hatena タグ:

Java SE 9 の予習 その2

Java

Java SE 9 の予習 その2です。

Java SE 8 でインタフェースにデフォルトメソッドと静的メソッドが実装できるようになりました。

しかし、使い勝手はお世辞にも良いとは言えませんでした。

Java でプログラムを組む上で重要なのはインタフェースの設計にあるからです。

デフォルトメソッドが実装された理由は Java SE 8 でインタフェースにメソッドを追加すると実装クラスに与える影響が大きく既存のプログラムに破綻を生じるケースも考えられたからです。

そんな事情からインタフェースにデフォルトメソッドが追加され実装がインタフェースにされるようになりました。

Java SE 9 からはさらにプライベートメソッドが実装できるようになります。

これでデフォルトメソッドの実装内容の非公開にしたい所をインタフェース経由で公開してしまうようなことは無くなります。

とりあえずプログラムを組んで動作確認をしてみました。

 

このプログラムの実行結果は次のようになります。

I ate strawberry cake. It was very delicious.
I ate tiramisu cake.
I will eat another TiramisuCake.
I ate cheese cake.
I will eat another cheese cake.
I ate chocolate cake.

Java SE 9 ではこのような小さな改良がたくさんあるようです。(^_^)

Java SE 9 の予習

Hatena タグ:

Java SE 9 の予習

Java

今日は私の○X回目の誕生日です。

今年は忘れられずにお祝いのプレゼントまでいただきました。(^_^)

いくつになっても誕生日を祝ってもらえるのは嬉しいものです。

と言うわけでお誕生日記念として今年の夏にリリース予定の Java SE 9 の予習をはじめます。

Java SE 9 と言えば Project Jigsaw, Project Kulla (JShell) が目玉となっています。

これらはこれから日本語での情報もたくさん出てくると思うので後回しとします。(既に最新Java情報局で記事があります。)

故に Java SE 9 を使うのであれば必要最低限これだけは覚えておきたいことを自分用メモとして載せておきます。

完全に自分用のメモです!

static <E> List<E> of()

Returns an immutable list containing zero elements. See Immutable List Static Factory Methods for details.

Type Parameters:
E – the List’s element type

Returns:
an empty List
 

public Stream<T> stream()

If a value is present, returns a sequential Stream containing only that value, otherwise returns an empty Stream.

API Note:
This method can be used to transform a Stream of optional elements to a Stream of present value elements:
 
     Stream<Optional<T>> os = ..
     Stream<T> s = os.flatMap(Optional::stream)
 
Returns:
the optional value as a Stream

 

static <T> Stream<T> ofNullable(T t)

Returns a sequential Stream containing a single element, if non-null, otherwise returns an empty Stream.

Type Parameters:
T – the type of stream elements

Parameters:
t – the single element

Returns:
a stream with a single element if the specified element is non-null, otherwise an empty stream

 

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

If a value is present, performs the given action with the value, otherwise performs the given empty-based action.

Parameters:
action – the action to be performed, if a value is presentemptyAction – the empty-based action to be performed, if no value is present

Throws:
NullPointerException – if a value is present and the given action is null, or no value is present and the given empty-based action is null.

 

public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

If a value is present, returns an Optional describing the value, otherwise returns an Optional produced by the supplying function.

Parameters:
supplier – the supplying function that produces an Optional to be returned

Returns:
returns an Optional describing the value of this Optional, if a value is present, otherwise an Optional produced by the supplying function.

Throws:
NullPointerException – if the supplying function is null or produces a null result

 

public static <T,A,R> Collector<T,?,R> filtering(Predicate<? super T> predicate, Collector<? super T,A,R> downstream)

Adapts a Collector to one accepting elements of the same type T by applying the predicate to each input element and only accumulating if the predicate returns true.

API Note:
The filtering() collectors are most useful when used in a multi-level reduction, such as downstream of a groupingBy or partitioningBy. For example, given a stream of Employee, to accumulate the employees in each department that have a salary above a certain threshold:
 
Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
   = employees.stream().collect(
     groupingBy(Employee::getDepartment,
                filtering(e -> e.getSalary() > 2000,
                          toSet())));
 
A filtering collector differs from a stream’s filter() operation. In this example, suppose there are no employees whose salary is above the threshold in some department. Using a filtering collector as shown above would result in a mapping from that department to an empty Set. If a stream filter() operation were done instead, there would be no mapping for that department at all.

Type Parameters:
T – the type of the input elements
A – intermediate accumulation type of the downstream collector
R – result type of collector

Parameters:
predicate – a predicate to be applied to the input elements
downstream – a collector which will accept values that match the predicate

Returns:
a collector which applies the predicate to the input elements and provides matching elements to the downstream collector

 

public static <T,U,A,R> Collector<T,?,R> flatMapping(Function<? super T,? extends Stream<? extends U>> mapper, Collector<? super U,A,R> downstream)

Adapts a Collector accepting elements of type U to one accepting elements of type T by applying a flat mapping function to each input element before accumulation. The flat mapping function maps an input element to a stream covering zero or more output elements that are then accumulated downstream. Each mapped stream is closed after its contents have been placed downstream. (If a mapped stream is null an empty stream is used, instead.)

API Note:
The flatMapping() collectors are most useful when used in a multi-level reduction, such as downstream of a groupingBy or partitioningBy. For example, given a stream of Order, to accumulate the set of line items for each customer:
 
Map<String, Set<LineItem>> itemsByCustomerName
   = orders.stream().collect(
     groupingBy(Order::getCustomerName,
                flatMapping(order -> order.getLineItems().stream(),
                            toSet())));
 
Type Parameters:
T – the type of the input elements
U – type of elements accepted by downstream collector
A – intermediate accumulation type of the downstream collector
R – result type of collector

Parameters:
mapper – a function to be applied to the input elements, which returns a stream of results
downstream – a collector which will receive the elements of the stream returned by mapper

Returns:
a collector which applies the mapping function to the input elements and provides the flat mapped results to the downstream collector

 

default Stream<T> takeWhile(Predicate<? super T> predicate)

Returns, if this stream is ordered, a stream consisting of the longest prefix of elements taken from this stream that match the given predicate. Otherwise returns, if this stream is unordered, a stream consisting of a subset of elements taken from this stream that match the given predicate.
 
If this stream is ordered then the longest prefix is a contiguous sequence of elements of this stream that match the given predicate. The first element of the sequence is the first element of this stream, and the element immediately following the last element of the sequence does not match the given predicate.

If this stream is unordered, and some (but not all) elements of this stream match the given predicate, then the behavior of this operation is nondeterministic; it is free to take any subset of matching elements (which includes the empty set).

Independent of whether this stream is ordered or unordered if all elements of this stream match the given predicate then this operation takes all elements (the result is the same as the input), or if no elements of the stream match the given predicate then no elements are taken (the result is an empty stream).

This is a short-circuiting stateful intermediate operation.

API Note:
While takeWhile() is generally a cheap operation on sequential stream pipelines, it can be quite expensive on ordered parallel pipelines, since the operation is constrained to return not just any valid prefix, but the longest prefix of elements in the encounter order. Using an unordered stream source (such as generate(Supplier)) or removing the ordering constraint with BaseStream.unordered() may result in significant speedups of takeWhile() in parallel pipelines, if the semantics of your situation permit. If consistency with encounter order is required, and you are experiencing poor performance or memory utilization with takeWhile() in parallel pipelines, switching to sequential execution with BaseStream.sequential() may improve performance.

Implementation Requirements:
The default implementation obtains the spliterator of this stream, wraps that spliterator so as to support the semantics of this operation on traversal, and returns a new stream associated with the wrapped spliterator. The returned stream preserves the execution characteristics of this stream (namely parallel or sequential execution as per BaseStream.isParallel()) but the wrapped spliterator may choose to not support splitting. When the returned stream is closed, the close handlers for both the returned and this stream are invoked.

Parameters:
predicate – a non-interfering, stateless predicate to apply to elements to determine the longest prefix of elements.

Returns:
the new stream

 

default Stream<T> dropWhile(Predicate<? super T> predicate)

Returns, if this stream is ordered, a stream consisting of the remaining elements of this stream after dropping the longest prefix of elements that match the given predicate. Otherwise returns, if this stream is unordered, a stream consisting of the remaining elements of this stream after dropping a subset of elements that match the given predicate.
 
If this stream is ordered then the longest prefix is a contiguous sequence of elements of this stream that match the given predicate. The first element of the sequence is the first element of this stream, and the element immediately following the last element of the sequence does not match the given predicate.

If this stream is unordered, and some (but not all) elements of this stream match the given predicate, then the behavior of this operation is nondeterministic; it is free to drop any subset of matching elements (which includes the empty set).

Independent of whether this stream is ordered or unordered if all elements of this stream match the given predicate then this operation drops all elements (the result is an empty stream), or if no elements of the stream match the given predicate then no elements are dropped (the result is the same as the input).

This is a stateful intermediate operation.

API Note:
While dropWhile() is generally a cheap operation on sequential stream pipelines, it can be quite expensive on ordered parallel pipelines, since the operation is constrained to return not just any valid prefix, but the longest prefix of elements in the encounter order. Using an unordered stream source (such as generate(Supplier)) or removing the ordering constraint with BaseStream.unordered() may result in significant speedups of dropWhile() in parallel pipelines, if the semantics of your situation permit. If consistency with encounter order is required, and you are experiencing poor performance or memory utilization with dropWhile() in parallel pipelines, switching to sequential execution with BaseStream.sequential() may improve performance.

Implementation Requirements:
The default implementation obtains the spliterator of this stream, wraps that spliterator so as to support the semantics of this operation on traversal, and returns a new stream associated with the wrapped spliterator. The returned stream preserves the execution characteristics of this stream (namely parallel or sequential execution as per BaseStream.isParallel()) but the wrapped spliterator may choose to not support splitting. When the returned stream is closed, the close handlers for both the returned and this stream are invoked.

Parameters:
predicate – a non-interfering, stateless predicate to apply to elements to determine the longest prefix of elements.

Returns:
the new stream

 

static IntStream iterate(int seed, IntPredicate hasNext, IntUnaryOperator next)

Returns a sequential ordered IntStream produced by iterative application of the given next function to an initial element, conditioned on satisfying the given hasNext predicate. The stream terminates as soon as the hasNext predicate returns false.
 
IntStream.iterate should produce the same sequence of elements as produced by the corresponding for-loop:

     for (int index=seed; hasNext.test(index); index = next.applyAsInt(index)) {
         …
     }
 

The resulting sequence may be empty if the hasNext predicate does not hold on the seed value. Otherwise the first element will be the supplied seed value, the next element (if present) will be the result of applying the next function to the seed value, and so on iteratively until the hasNext predicate indicates that the stream should terminate.

The action of applying the hasNext predicate to an element happens-before the action of applying the next function to that element. The action of applying the next function for one element happens-before the action of applying the hasNext predicate for subsequent elements. For any given element an action may be performed in whatever thread the library chooses.

Parameters:
seed – the initial element
hasNext – a predicate to apply to elements to determine when the stream must terminate.
next – a function to be applied to the previous element to produce a new element

Returns:
a new sequential IntStream

 

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

Returns a sequential ordered Stream produced by iterative application of the given next function to an initial element, conditioned on satisfying the given hasNext predicate. The stream terminates as soon as the hasNext predicate returns false.
 
Stream.iterate should produce the same sequence of elements as produced by the corresponding for-loop:

     for (T index=seed; hasNext.test(index); index = next.apply(index)) {
         …
     }
 

The resulting sequence may be empty if the hasNext predicate does not hold on the seed value. Otherwise the first element will be the supplied seed value, the next element (if present) will be the result of applying the next function to the seed value, and so on iteratively until the hasNext predicate indicates that the stream should terminate.

The action of applying the hasNext predicate to an element happens-before the action of applying the next function to that element. The action of applying the next function for one element happens-before the action of applying the hasNext predicate for subsequent elements. For any given element an action may be performed in whatever thread the library chooses.

Type Parameters:
T – the type of stream elements

Parameters:
seed – the initial element
hasNext – a predicate to apply to elements to determine when the stream must terminate.
next – a function to be applied to the previous element to produce a new element

Returns:
a new sequential Stream

 

API ドキュメントが英語しかないのが残念(>_<)

正式リリースされる頃には日本語版が出ることを祈ろう!

Java SE 8 からの痒いところに手が届いたようなアップデートだけどかなり便利になる。

なぜ初めからこうしなかったんだろうと思うほどに。

でも zip, pair はまだ無いまま・・・

Java SE 10 まで待つことになるのか必要ないと判断されたのか?

他にもいろいろ細かいところが良くなっているようだから正式リリースが楽しみですね!

Hatena タグ:

Java Puzzlers Advent Calendar 2016 – Coffee Break —

Java

このエントリーは http://qiita.com/advent-calendar/2016/java_puzzlers の 21 日目です。

昨日は @zr_tex8r さんのの「ループ以外の文にラベルは付けられるか?」でした。

明日は @khasunuma さんの「誰も投稿しそうにないので、もう少し頑張ってみる」です。

連日高度な Java Puzzle が投稿されていて楽しませていただいてます。

「ジャバチョットデキル」という凄い人たちの投稿でクリティカルヒットを食らってダウンしてます。(^_^;

ここらへんで CoffeeBreak ということで息抜きパズルでエントリーさせていただきます。

古典的なありふれたネタですがお楽しみください。

ちなみにこのプログラムはパズル用なので実用性の欠片もありません。

問題

次のプログラムをコンパイル、実行すると標準出力にどんな結果を表示するでしょうか?

(1)

1767504129 pool-1-thread-1
1767504129 pool-1-thread-3
1767504129 pool-1-thread-2
1767504129 pool-1-thread-4
-243838107 ForkJoinPool.commonPool-worker-25
1829062017 ForkJoinPool.commonPool-worker-18
1664456421 ForkJoinPool.commonPool-worker-18
856650241 ForkJoinPool.commonPool-worker-25
executor.shutdown()

ExecutorService を使った方は同じハッシュ・コード値を必ず返す。

(2)

1767504129 pool-1-thread-4
1767504129 pool-1-thread-2
1767504129 pool-1-thread-1
1767504129 pool-1-thread-3
1829062017 ForkJoinPool.commonPool-worker-25
1829062017 ForkJoinPool.commonPool-worker-18
1829062017 ForkJoinPool.commonPool-worker-18
1829062017 ForkJoinPool.commonPool-worker-25
executor.shutdown()

ExecutorService、ForkJoin ともに同じハッシュ・コード値を必ず返す。

(3)

-230323071 pool-1-thread-1
1767504129 pool-1-thread-4
-2046939163 pool-1-thread-3
-230323071 pool-1-thread-2
-243838107 ForkJoinPool.commonPool-worker-25
1829062017 ForkJoinPool.commonPool-worker-18
1664456421 ForkJoinPool.commonPool-worker-18
856650241 ForkJoinPool.commonPool-worker-25
executor.shutdown()

同じハッシュ・コード値を返す場合もある

(4)

1647295788 pool-1-thread-1
-591109637 pool-1-thread-4
1767504129 pool-1-thread-2
357637727 pool-1-thread-3
-243838107 ForkJoinPool.commonPool-worker-25
1829062017 ForkJoinPool.commonPool-worker-18
1664456421 ForkJoinPool.commonPool-worker-18
856650241 ForkJoinPool.commonPool-worker-25
executor.shutdown()

おのおのユニークなハッシュ・コード値を返す。

(5)

実行時例外

(6)

コンパイルエラー

 

答え

正解は‥‥

 

 

 

 

 

 

(1) ではありません。

 

 

 

(2)  でもありません。

 

 

 

(3) が正解といいたいところですが違います。

実はこのように出力されることもあります。

ただし、100 パーセントこのように出力される保証はなくプログラムのコードには致命的な大きな問題がひそんでいます。

よって、不正解ということでご了承くださいませ。

 

 

 

正解は (5) 実行時例外です。

java.util.ConcurrentModificationException が投げられます。

65 行目の System.out.println(friends.hashCode() + ” ” + Thread.currentThread().getName()); が原因です。

java.util.ConcurrentModificationException とはどんな例外なのでしょうか?

Javadoc を見てみましょう。

この例外は、オブジェクトの並行変更を検出したメソッドによって、そのような変更が許可されていない場合にスローされます。
 
たとえば、あるスレッドが Collection で繰り返し処理を行なっている間に、別のスレッドがその Collection を変更することは一般に許可されません。

通常、そのような環境では、繰り返し処理の結果は保証されません。

いくつかのイテレータ (Iterator) の実装 (JRE が提供するすべての一般的な目的のコレクションの実装の、イテレータの実装を含む) は、その動作が検出された場合にこの例外をスローすることを選択できます。

この例外をスローするイテレータは、フェイルファストイテレータと呼ばれます。

イテレータは、将来の予測できない時点において予測できない動作が発生する危険を回避するために、ただちにかつ手際よく例外をスローします。

この例外は、オブジェクトが別のスレッドによって並行して更新されていないことを必ずしも示しているわけではありません。

単一のスレッドが、オブジェクトの規約に違反する一連のメソッドを発行した場合、オブジェクトはこの例外をスローします。

たとえば、フェイルファストイテレータを持つコレクションの繰り返し処理を行いながら、スレッドがコレクションを直接修正する場合、イテレータはこの例外をスローします。

通常、非同期の並行変更がある場合、確かな保証を行うことは不可能なので、フェイルファストの動作を保証することはできません。

フェイルファストオペレーションは最善努力原則に基づき、ConcurrentModificationException をスローします。

したがって、正確を期すためにこの例外に依存するプログラムを書くことは誤りです。

ConcurrentModificationException は、バグを検出するためにのみ使用してください。

以上、 Javadoc より

つまり、 Java の同期化コレクションはマルチスレッドなどによる並行的な変更には完全に対応できないということです。

だから並行的な変更への対処はイテレーション開始後に Collection が変更されたのを検出すると ConcurrentModificationException 例外をただちに投げるというフェイルファストという設計になっている。

ただし、このフェイルファスト設計は実行性能に与える影響を抑えるためにそれほど優秀な設計にはなってないようです。

では、この問題の鍵はどこにあるのだろう?

どうして? Iterator で回してないのにと思われる人は純な心の持ち主でしょう。

hashCode() メソッドの実装は次のようになっています。

拡張 for 文を使っていますね。

これは内部でイテレータを使ってます。だから java.util.ConcurrentModificationException が投げられます。

もう少し確認するために次のような変更をプログラムに加えてみましょう。

65 行目の System.out.println(friends.hashCode() + ” ” + Thread.currentThread().getName()); を

System.out.println(“My Friends: ” + friends + ” ” + Thread.currentThread().getName()); に変更して実行してみます。

これでも java.util.ConcurrentModificationException が投げられます。

どうしてでしょう?

まず、文字列の連結操作により StringBuilder クラスの次のメソッドが呼ばれます。

続いて String クラスの次のメソッドが呼ばれます。

そして、AbstractCollection<E> クラスの次のメソッドが実行されます。

おおっ! Iterator でぶん回してますね

問題の hashCode() メソッド同様に内部で Iterator を使ってます。

このように間接的に Iterator を使っていることに気づかずに致命的なミスをおかしてしまう可能性があります。

Collection の取り扱いには細心の注意が必要です。

それではこのプログラムの修正はどうすればいいでしょうか?

この問題のプログラムは Collection への要素の追加、削除を次のように synchronized メソッドで排他制御を行ってます。

これでは Collection をイテレーションしている間に別のスレッドによる変更操作が行われてしまいます。

排他制御を行うには public void update() メソッドを public synchronized void update() メソッドに変更すれば OK です。

要素の追加、削除のメソッドは排他制御を行う必要はこれでなくなります。

synchronized による排他制御を行いたくない場合は ReentrantLock を使う方法があります。

最後に CopyOnWriteArrayList<E> を使う方法があります。

ただし、これは今までの排他制御とは異なります。

CopyOnWriteArrayList<E> の Javadoc を読んでみましょう。

public class CopyOnWriteArrayList<E> extends Object implements List<E>, RandomAccess, Cloneable, Serializable

基になる配列の新しいコピーを作成することにより、すべての推移的操作(add、setなど)が実装されるArrayListのスレッド・セーフな変数です。
 
通常、これは非常に効率が悪いのですが、トラバーサル操作が変更を数の点で大幅に上回る場合には、代替手段よりも効率が良い場合があります。

また、これは、トラバーサルを同期できない場合や、同期することを望まないが、並行スレッド間の干渉を排除する必要がある場合に有用です。

「スナップショット」スタイルのイテレータ・メソッドは、イテレータの作成時点での配列状態への参照を使用します。

この配列がイテレータの有効期間中に変更されることは決してないため、干渉は不可能であり、イテレータはConcurrentModificationExceptionをスローしないことが保証されます。

イテレータは、イテレータの作成以降のリストへの追加、削除、または変更を反映しません。

イテレータ自体に対する要素変更操作(remove、setおよびadd)はサポートされません。これらのメソッドは、UnsupportedOperationExceptionをスローします。

nullを含むすべての要素が許可されます。

メモリー整合性効果: ほかの並行処理コレクションと同様、オブジェクトをCopyOnWriteArrayListに配置する前のスレッド内のアクションは、別のスレッドでのその要素へのアクセスまたはCopyOnWriteArrayListからの削除に続くアクションよりも前に発生します。

このクラスは、Java Collections Frameworkのメンバーです。

つまり、スナップショット(コピー)を作ってそれをイテレーションすることによってスレッド・セーフを可能にしているようです。

private final List<String> friends = new ArrayList<>(16); を

private final CopyOnWriteArrayList<String> friends = new CopyOnWriteArrayList<>(); に変更するだけのお手軽仕様です。

ただし、CopyOnWriteArrayList<E> は初期容量を設定できないのでお間違いなく!

いかがでしたでしょうか?

本当に古典的なありふれたパズルですが懐かしさと初めて java.util.ConcurrentModificationException を投げられたときの ??? ってのを思い出していただければ幸いです。

ここでネタばらし・・・ この問題は 「Java 並行処理プログラミング」という古い本にも載っているほど超有名なネタでした。

これだけだと CoffeeBreak ネタとしては面白みに欠けていますのでグリコのキャラメルのおまけのような問題をもう一問どうぞ。

ていうか、これが本題です。

グリコのキャラメルのおまけのような問題

次のプログラムをコンパイル、実行すると標準出力にどんな結果を表示するでしょうか?

ただし、public static void parkUntil(long deadline) メソッドの理由無き復帰はないものとする。

(1)

今日も一日がんばるぞい!
1時 2時 3時
□フo(^-^)コーヒーブレイク
そろそろ休憩おわりにしようか?
4時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
(゙ `-´)/ コラッ!!  休憩は3時間だぞ。働け!
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
7時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
コーヒーブレイク終了
9時 10時
仕事終わった! 愛する家族の元へ帰ろう!

(2)

今日も一日がんばるぞい!
1時 2時 3時
□フo(^-^)コーヒーブレイク
3時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
そろそろ休憩おわりにしようか?
4時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
(゙ `-´)/ コラッ!!  休憩は3時間だぞ。働け!
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
7時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
コーヒーブレイク終了
9時 10時
仕事終わった! 愛する家族の元へ帰ろう!

(3)

実行時例外

(4)

コンパイルエラー

 

答え

 

 

 

 

 

 

 

正解は‥‥

 

 

 

 

(1) ではありません。

 

 

 

 

 

(2) です。

worker スレッドが開始された直後に LockSupport.unpark(worker); が実行されます。(45 行目)

これは引数で指定したスレッドにパーミットを与えます。

このパーミットは一つだけ蓄積可能となります。

よって、worker スレッドの LockSupport.parkUntil(t); (30 行目) はパーミットを消費してすぐにリターンされます。

故に標準出力に

今日も一日がんばるぞい!
1時 2時 3時
□フo(^-^)コーヒーブレイク
3時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~

と表示されます。

そして 48行目の LockSupport.unpark(worker); が実行されて

そろそろ休憩おわりにしようか?
4時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~

と続きます。

while ループで再び LockSupport.parkUntil(t); が実行されます。

指定された待機時間を経過してないのでスレッドは再び待機します。

51 行目で worker.interrupt(); と割り込みをかけます。

ところがこの割り込みに対して InterruptedExceptionがスローされません。

割り込みによる処理をなにもしていないので LockSupport.parkUntil(t); による指定された待機時間までの待機は解除されすぐにリターンされます。

while ループで指定された待機時間まで延々と標準出力に次のように出力されます。

(゙ `-´)/ コラッ!!  休憩は3時間だぞ。働け!
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
6時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
7時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
            .
            .
            .
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
8時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
コーヒーブレイク終了
9時 10時
仕事終わった! 愛する家族の元へ帰ろう!

これをスッキリした出力にするためには 45 行目の LockSupport.unpark(worker); を削除し、

worker スレッドへの割り込みの対処を次のようにすれば期待する出力が得られます。

今日も一日がんばるぞい!
1時 2時 3時
□フo(^-^)コーヒーブレイク
そろそろ休憩おわりにしようか?
4時やん。 まだ、コーヒーブレイク タイム。 □フo(^O^)プハァ~
(゙ `-´)/ コラッ!!  休憩は3時間だぞ。働け!
はい、はい。
6時 7時 8時 9時 10時 仕事終わった! 愛する家族の元へ帰ろう!

参考にこのプログラムで使った java.lang.Object java.util.concurrent.locks.LockSupport クラスのメソッドの Javadoc を載せておきます。

public static void unpark(Thread thread)

指定されたスレッドのパーミットが使用可能でない場合に、使用可能にします。

スレッドがparkでブロックされた場合は、ブロックを解除します。

それ以外の場合は、そのparkの次回の呼出しがブロックされないよう保証されます。

指定されたスレッドが起動していない場合、この操作の効果は一切保証されません。

パラメータ:thread – unparkを実行するスレッドまたはnull。その場合、この操作に効果はない

public static void parkUntil(long deadline)

パーミットが利用可能でない場合、指定された期限まで、スレッドのスケジューリングに関して現在のスレッドを無効にします。
 
パーミットが使用可能な場合、これは消費され、呼出しはただちに復帰します。

それ以外の場合、現在のスレッドは、スレッド・スケジューリングに関して無効になり、次の4つのいずれかが起きるまで待機します。
 
•ほかのスレッドが、現在のスレッドをターゲットとしてunparkを呼び出す。
•ほかのスレッドが現在のスレッドに割り込みを行う。または
•指定された期限が経過する。または
•呼出しが、見せかけで(理由もなく)復帰する。

このメソッドは、これらのどれがメソッド復帰の原因となったかはレポートしません。

呼出し側は、スレッドの初回parkの原因となった状態を再チェックする必要があります。

呼出し側は、スレッドの割込み状態や、復帰時の現在時刻なども判定できます。

パラメータ:deadline – 待機用の、元期からのミリ秒単位の絶対時間

以上、Coffee Break ネタでした。(^_^)

さらに、おまけ

次のプログラムの出力結果を答えよ。

 

 

 

 

答え

 

 

 

 

 

Results of Math and StrictMath were not the same.
-2
true
false

これはクイズ要素も引っかけ要素もまるで無いです。

強いてあげれば3行目の出力結果くらいですね。

よくあるオーバーフローねたです。(^_^;

API ドキュメントにすべて解説してありますので知らなくて興味のある人は覗いてみましょう。

java.lang.Object java.lang.Math public static double log(double a)

java.lang.Object java.lang.StrictMath public static double log(double a)

public static int floorDiv(int x, int y)

public static int floorMod(int x, int y)

以上、お終い!

Hatena タグ:

Atom をとりあえずインストール

Computer Java Ubuntu

Windows 環境で Valhalla がビルドできなくなって遊べなくなったので Ubuntu で遊べるように最近ブレイク中の Atom をインストールしてプログラムを実行できるようにしてみた。

注意: なぜ Windows 環境でビルドできなくなったか原因を調べて対処しないの?ってことは禁句です。私には無理!!

入れるパッケージはネットで適当に調べて Script を導入すればよさげなので早速試してみた。

他にもネット上の情報を拾い集めて入れてみた。

とりあえず Java が実行できればいいので Script の設定をφ(..)メモメモ

[編集] → [環境設定] → init.coffee に使いたい Java のパスを記述する。

process.env.PATH = [“使いたい Java のパス“, process.env.PATH].join(“:”);

1

あと、Script の出力画面のフォントがこのままだと小さくて見づらいので大きく変更する。

[編集] → [スタイルシート] → styles.less に次の設定を追加する。

.script-view .line{
    font-size: 18px;
}

2

これで Valhalla を楽しむ準備ができた!

確認してみる。

3

Script の出力画面のフォントサイズもこれで OK!

はい! 自分用のピンポイントメモエントリーでした。

 

ここで重大な問題が・・・

Atom の使い方がよく解らん。。。


« 古い記事 新しい記事 »