分かち合い:Java 8話題のない8つの機能

6086 ワード

最近Java 8に関する文章を読んで、皆さんに分かち合いました。
http://www.infoq.com/cn/articles/Java-8-Quiet-Features?utm_source=infoq&utm_medium=popur_リンクス.ホームパーティー
 
タイムスタンプロック
これまで、マルチスレッドコードはサーバー開発者の毒薬です。Javaのコアライブラリは、共有リソースにアクセスするスレッド待ち時間を減らすために、さまざまな複雑な使い方を繰り返している。その中の一つは経典の読み書きロックです。コードを二つの部分に分けます。相互に反発する書き込み操作と相互に反発する必要のない読み操作が必要です。
表面的にはよさそうです。問題は読み書きロックが極めて遅い(最大10倍)かもしれないということです。これはもう初志とは違っています。Java 8は、タイムスタンプロックという新しい読み書きロックを導入しました。いいニュースはこいつが本当に早いです。悪いニュースはもっと複雑に使います。もっと多くの状態があります。また、これはスレッドが自分とデッドロックする可能性があることを意味します。
タイムスタンプロックには「楽観」モードがあります。このモードではロック操作のたびにタイムスタンプを返します。ロック解除のたびに対応するタイムスタンプを提供する必要があります。もしスレッドが書き込みロックを要求した時、このロックはたまたま読み取り操作によって保有されていた場合、この読み取り操作のアンロックは無効になります。この時はアプリをもう一度やり直す必要があります。悲観モードのロックを使うかもしれません。これを自分で解決しなければなりません。そしてタイムスタンプはロックだけ解除できます。この点は十分に注意しなければなりません。
 
このロックの例を見てみましょう。
long stamp = lock.tryOptimisticRead(); //      ——   
work(); //                
if (lock.validate(stamp)){
       //  !        
}
else {
       //                  ,      
       //   ——            
	
            stamp = lock.readLock(); //         ,   
       try {
                 //            
                 work();

       }
       finally {
            lock.unlock(stamp); //           
       }
}
コンバイナー
Java 8のもう一つの優れた機能は「加算器」を併発することであり、大規模な動作のコードに特に意味があります。一つの基本的な合併モードは一つのカウンタに対して読み書きをすることです。それ自体は、この問題を処理するための多くの方法がありますが、Java 8より提供される方法は、効率的または優雅ではありません。
これまでは、CPUの「比較・交換」コマンド(CAS)を直接利用して、原子系(Atomics)で試験し、カウンタの値を設定していました。問題は、CAS命令が競争で失敗した場合、AtomicInteger類が死ぬなど、無限ループの中でCAS命令を試行し、成功するまで試行し続けることです。この実現は競合確率が高い環境では非常に遅いことが証明された。
Java 8のLongAdderを見に来ました。この一連の種類は大量の並列読み書き数値のコードに便利な解決方法を提供しています。使用はとても簡単です。LongAddrオブジェクトを初期化し、そのadd()とintValue()方法を使用してカウンタを積算し、サンプリングします。
これは、従来のAtomic類とは異なり、CASコマンドが競合により失敗した場合、AdderはCPUを占有していないが、現在のスレッドに内部セルオブジェクトを割り当ててカウンタの増分を記憶する。そしてこの値は他の処理対象のセルオブジェクトと一緒にintValue()の結果に加算されます。これはCAS命令を繰り返し使用するか、他のスレッドをブロックする可能性を低減する。
あなた自身に聞いたら、いつコンバイナーを使って原子類ではなくカウンタを管理しますか?簡単な答えはずっとそうしています。
並列並べ替え
合併加算器がカウントを加速できるように、Java 8はまた、簡潔な方法で順序付けを加速する。この秘訣は簡単です。もうこのようにしません。
Array.sort(myArray);
そうすることです
Arrays.parallelSort(myArray);
これは自動的に目標配列をいくつかの部分に分割して、これらの部分は独立したCPUコアに置いて実行され、結果を統合します。ここで唯一の注意点として、マルチスレッドが大量に使用されている環境では、例えば忙しいWebコンテナのように、この方法の利点が弱まり(90%以上低減される)、CPUコンテキストの切り替えがより多くなってオーバーヘッドが増大するためである。
新しい日付インターフェースに切り替えます。
Java 8は全く新しいdate-timeインターフェースを導入しました。現在のインターフェースのほとんどの方法はすでにdeprecatedとしてマークされています。新しいインターフェースが出る時だと知っています。新しい日付インターフェースはJavaコアライブラリに使いやすさと正確さをもたらしていますが、以前はJoda timeでしかこのような効果を達成できませんでした。
どんな新しいインターフェースと同じで、良いニュースはインターフェースがより優雅で強くなることです。しかし、残念なことに、まだ多くのコードが古いインターフェースを使用しています。この短い時間では変更されません。
古いインターフェースに接続するために、古いDate類はToInstant()方法を追加し、Dateを新しい表示形式に変換します。新しいインターフェースのメリットを享受しながら、古い日付表示形式だけを受け入れるインターフェースを考慮すると、この方法は特に効率的になります。
オペレーティングシステムのプロセスを制御する
あなたのコードの中でオペレーティングシステムのプロセスを起動したいです。JNIの呼び出しで完成できます。しかし、このものはよく分かります。あなたは思いがけない結果を得ることができます。そして、一緒に悪い異常を伴います。
それでも、これは避けられないことです。しかし、プロセスにはもう一つの嫌な特性があります。Javaから現在進行中の問題は、プロセスが起動すると制御しにくいということです。
この問題を解決するために、Java 8はProcess類に三箇新の方法を導入しました。
一つのプロセスを終了すると、成功率は以前よりずっと高いです。isAlive-あなたが起動したプロセスが生きているかどうかを調べます。waitFor()を積載しました。今はプロセスが終わるまでの時間を指定できます。プロセスが成功したら、このインターフェースは戻ってきます。タイムアウトしたら戻ってきます。手動で終了する可能性があります。これらの新しい方法をどうやって使うかについてのいい例が二つあります。
もしプロセスが規定の時間内に終了しないなら、それを中止して前に進みます。
if (process.wait(MY_TIMEOUT, TimeUnit.MILLISECONDS)){
//   }
else {
process.destroyForcibly();
}
コードが終了する前に、すべてのプロセスが終了したことを確認します。ゾンビプロセスはシステムの資源をどんどん使い果たします。
for (Process p : processes) {
       if (p.isAlive()) {
             p.destroyForcibly();
       }
}
精確な数字演算
デジタルオーバーフローは嫌なバグを引き起こします。本質的には間違いがないからです。一部のシステムでは、整数値が増加し続けています(カウンタなど)、オーバーフローの問題が特に深刻です。これらのケースの中で、製品は進化段階でよく動いています。商用後も長い間大丈夫ですが、最終的には変な故障が起こります。
この問題を解決するために、Java 8は、Mathクラスのために、重要なコードがオーバーフローの影響を受けないように、いくつかの新しい「精確型」方法を追加しました。その方法は、演算がその精度範囲を超えたとき、未確認のArthmeticExceptionを投げ出します。
int safeC = Math.multiplyExact(bigA, bigB); 
//       +-2^31,    ArithmeticException  
唯一の悪いところは溢れ出るコードを自分で探さなければなりません。いずれにしても、自動的な解決策はない。これらのインターフェースがあるのはないよりいいと思います。
安全な乱数発生器
過去数年間、Javaはセキュリティ・ホールのために非難されてきた。合理的であろうとなかろうと、Javaは仮想マシンとフレーム層を強化するために大量の仕事をしています。乱数がランダム性の低いシードから源を発する場合、鍵やハッシュ敏感情報を乱数で生成するシステムは攻撃を受けやすい。
これまで乱数発生アルゴリズムは開発者が決定してきた。しかし問題は、もしあなたが欲しいアルゴリズムが特定のハードウェア、オペレーティングシステム、仮想マシンに依存するなら、あなたはそれを実現できるとは限らない。この場合、アプリケーションはより弱いデフォルトジェネレータを使用する傾向があり、これにより彼らはより大きなリスクにさらされている。
Java 8は新しい方法を追加しました。SecureRandom.get Instance Strong()といいます。仮想マシンに安全な乱数発生器を選択させることを目的としています。あなたのコードがオペレーティングシステム、ハードウェア、仮想マシンを完全にコントロールできないなら、(もしあなたのプログラムがクラウドやPaaSに展開されるなら、これはよくあることです)このインターフェースを使うことを真剣に考えてみてください。
オプションの参照
空の針は「足の指を蹴る」と同じです。歩き方を覚えてからあなたと一緒にいます。今はいくら頭がいいとしても、あなたはこの間違いを犯します。この古い問題を解決するために、Java 8はOptionalという新しいテンプレートを導入しました。
このテンプレートは、ScaraおよびHashkellから参考にされており、関数または関数に伝達されたことを明確にするための参照は空である可能性があります。これによって、古い文書や見たコードに過度に依存して変動する人は、ある引用が空である可能性があるかどうかを推測する必要がありません。
Optional<User> tryFindUser(int userID) {
または
void processUser(User user, Optional<Cart> shoppingCart) {
Optionalテンプレートには、サンプルをより便利にする関数があります。例えば、isPresent(isPresent)は、この値が空でないかどうか、またはifPresent()はLamda関数を過去に伝えることができます。isPresent()がtrueに戻ると、このLamber関数が実行されます。悪いところはJava 8の新しい日付インターフェースと同じように、このようなパターンがだんだん流行しています。私達が使っている倉庫や日常設計に浸透するには、時間と仕事量が必要です。
value.ifPresent(System.out::print);
 最后に、小编と自分の子供靴たちはこの前に宝を洗う店をやりました。楽しいというのは、なぜ楽しいというかというと、小编はずっと自分の微信の公式アカウントを运営しています。もちろん、プログラミング技术についてです。みんなも検索できます。 注目