異常とマルチスレッド

異常な第一章

1.1珍しいコンセプト

最終的には非JVM通常の停止にそこにつながる、プログラムの実施の過程で異常な状況を指します。

Javaなどのオブジェクト指向プログラミング言語で、クラス自体が異常であり、例外は、例外オブジェクトを作成することであり、例外オブジェクトを投げます。Javaは取り扱い割り込みハンドラの例外への道です。

1.2システムの異常

例外はルートクラスでありjava.lang.Throwable、2つのサブクラスが下にありますjava.lang.Errorjava.lang.Exception、異常は通常、後者であることを特徴とします。

Throwableのシステム:

  • Error:重大なエラー、エラーは、それが唯一のを避けるために達成することができ、通じ扱うことができません。
  • Exception:手段例外は道のプログラマーによって発生した例外は、コードを修正することができ、プログラムの実行を継続し、適切に対処する必要があることです。

Throwableの一般的な方法:

  • public void printStackTrace():例外の印刷の詳細については。

    また、開発およびデバッグ段階における異常の位置を含む、異常の種類の理由を含む、異常、のprintStackTraceを使用していました

  • public string getMessage():例外が発生した理由は、取得します。

    それは間違った理由を促し、ユーザーに

  • public String toString():(なし)例外と例外の記述の型を取得します。

異常な、APIのクエリにコピーされた珍しいシンプルなクラス名を置くことができます

分析プロセスの1.3異常世代

1567066501414

章ハンドルの例外

2.1例外スローを投げます

Javaでは、それが提供してスロー指定された例外オブジェクトをスローするために使用されたキーワードを、。

使用方法:

  1. (あなたがあなた自身のメッセージを書き込むことができます)いくつかのヒントをパッケージ化、例外オブジェクトを作成します。
  2. 例外オブジェクトは、呼び出し側に通知する必要があるキーワード投によって完了することができ、使用される方法でスロー、例外オブジェクトを投げるで呼び出し側に例外オブジェクトを渡し、現在のメソッドの終了が実行されます。

フォーマットを使用します:

throw new 异常类名(参数);

例えば:

public class throw关键字 {
    public static void main(String[] args) {
        int[] arr = null;
        /* 传入为null的数组 */
        int element = getElement(arr, 1);
        System.out.println(element);
    }
    public static int getElement(int[] arr,int index){
        if (arr == null){
            /* 手动抛出异常 */
            throw new NullPointerException("这是数组是null");
        }
        return arr[index];
    }
}

2.2オブジェクトが空でない決定しました

クラスは、いくつかの静的ユーティリティメソッド組成物によって、これらの方法はヌル保存(ヌルポインタの安全性)またはヌル寛容(トレランスヌルポインタ)である、オブジェクト、そのソースコードは、オブジェクトが放物線ヌル値であります異常動作。

  • public static<T> T requireNonNull(T obj):指定参照オブジェクトがnullではありません。

メソッドのソースコードは、上記:

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

使用することの利点:時間が空であるかどうかを決定する際には、唯一の自己決意のコードの量を減少させる、か否かNULLポインタを決定することができるメソッドを呼び出す必要が

例えば:

import java.util.Objects;

public class throw关键字 {
    public static void main(String[] args) {
        int[] arr = null;
        int element = getElement(arr, 1);
        System.out.println(element);
    }
    public static int getElement(int[] arr,int index){
//        if (arr == null){
//            throw new NullPointerException("这是数组是null");
//        }
        /* 将上述抛出异常换成下面的方法,效果相同,使用更简洁 */
        Objects.requireNonNull(arr,"数组为null");
        return arr[index];
    }
}

2.3ステートメントは、例外がスローされます

呼び出し元に報告書のうちアイデンティティの問題。コンパイラハンドルの例外を投げる方法投げ以内にキャッチされていない場合、異常、および、それには、スローに対処するための発信者を聞かせてに宣言する必要があります。

キーワードは、スロー文で使用される方法で、(例外をスロー)、例外を処理しない、現在の方法を示すために使用されるのではなく、例外を処理するメソッドの呼び出し元を思い出させます。

珍しいの文フォーマット:

修饰符 返回值类型 方法名(参数) throws AAAExcetion,BBBExcetion...{
    throw new AAAExcetion("产生原因");
    throw new BBBExcetion("产生原因");
}

注意事項:

  • キーワードは、メソッド宣言で記述する必要がありますスロー。
  • キーワードは、バック例外が例外または例外のサブクラスを宣言する必要がありますスロー。
  • 複数の内部メソッドは例外オブジェクトをスローした場合、その後、バックスローはまた、複数の異常を宣言しなければなりません。父と息子の関係を、より少ない異常親への直接の文のようなオブジェクトをスロー複数の例外がある場合。
  • メソッドが例外をスロー呼び出し文では、我々は異常に対処する必要がいずれかのthrowステートメントは、呼び出し元の処理方法に、そして最終的にはJVMに、スロー引き続き使用する、またはしようと宣言した...キャッチハンドルの例外に自分自身

例えば:

/* 自定义异常 */
class myException extends Exception{
    public myException(){}
    public myException(String s){
        super(s);
    }
}
public class 自定义异常类 {
    /* 定义异常的函数 */
    public static String func(int score) throws myException {
        System.out.println("1");
        if (score >= 0 && score <= 100) {
            return "ok";
        } else {
            throw new myException("错误输入");
        }
    }
    public static void main(String[] args) {
        /* 捕获异常 */
        try{
            String str1 = func(88);
            System.out.println(str1);
            String str2 = func(120);
            System.out.println(str2);

        } catch (myException e){
            System.out.println("异常信息为:"+e.getMessage());
        } finally {
            System.out.println("结尾代码,都会出现这句话");
        }
        System.out.println("不管上面代码出错否,都不会中断程序,都会出现这句话");
    }
}

2.4キャッチ例外は試す...キャッチ

例外が発生した場合、それはすぐにプログラムを終了しますので、私たちは、例外を処理する必要があります。

  1. この方法は取り扱いが、(スロー)に対処するためのメソッドの呼び出し元で声明を出し盛り付けしません。
  2. ハンドルの例外に使用する方法で文のtry-catchブロックを

try-catchの方法は、例外をキャッチすることです

  • キャッチ例外:異常の文でJavaが指定した方法で発生する可能性の異常を処理、キャプチャ対象。

キャッチ例外の構文は次のとおりです。

try {
    编写可能出现异常的代码
} catch (异常类型 e) {
    处理异常的代码
    // 记录日志/打印异常信息/继续抛出异常
} 

例外情報を取得する方法:

Throwableクラスは、閲覧メソッドの数を定義します。

  • public String getMessage():記述情報を取得し、その理由(ショートメッセージ)の異常

  • public String toString():異常の種類と異常記述情報(詳細情報)を取得

  • public void printStackTrace():(例外情報は最も包括的な印刷され、この方法は、デフォルトで使用され、JVM印刷例外オブジェクト)例外スタックトレース情報を出力コンソールへの印刷

    開発およびデバッグ段階での例外の理由、珍しい、異常な位置の種類が含まれている、我々はのprintStackTraceを使用する必要がありました。

2.5異常注意事項

  • 例外が捕捉したり、実行時にスローされていないその文に対処することはできませんスローされます。
  • 最後にreturn文がある場合、それはこのような状況を回避するために、最終的に結果を返すことはありません。
  • 親クラスのメソッドが例外を複数スローした場合、サブクラスはスーパークラスのメソッドをオーバーライドし、同じ例外クラスを投げるか、親は親クラスであるか、サブクラスの例外がスローされていません。
  • 親クラスのメソッドが例外をスローしない場合は、その後、サブクラスの例外を生成し、異常のあるとき、親クラスのメソッドをオーバーライドし、またサブクラスを投げることができる、あなただけの文を投げていない、例外をキャッチすることができます。

  • 試した後...キャッチfinallyブロックは、一般的にリサイクルのために使用され、その中でコードが実行される、添加してもよいです。

  • 加えて、異常の分類、キャッチ例外であるよりもキャッチされない例外キャッチされない例外あって、Errorクラスとの、直接的、間接的およびサブクラスのサブクラスでそのRuntimeExceptionクラスとその直接および間接のサブクラスのサブクラスを。

    使用して、例外をキャッチし、起こることができない例外をキャッチすることはできません声明を配置しようとすると、それ以外の場合はエラーになり、

例I:

class Fu {
    public void method1() throws Exception{}
    public void method2() throws Exception{}
    public void method3() throws Exception{}
    public void method4() {}
}
class Zi extends Fu {
    /* 父类抛出异常的方法重写,子类抛出与父类相同的异常 */
    @Override
    public void method1() throws Exception{}
    /* 父类抛出异常的方法重写,子类抛出父类异常的子类 */
    @Override
    public void method2() throws IndexOutOfBoundsException{}
    /* 父类抛出异常的方法重写,子类不抛出异常 */
    @Override
    public void method3() {}
    /* 如果父类没有抛出异常,那么子类也不能抛出异常,若是存在异常,自行捕获 */
    @Override
    public void method4() {
        try {
            throw new Exception();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class 子类重写父类抛出异常函数 {
}

例II:

import java.io.IOException;

public class 不可能出现异常的代码 {
    public static void main(String[] args) {
        try{
            System.out.println("111");
        } catch (IOException E){// 会报错
            System.out.println("捕获异常");
        } catch (IndexOutOfBoundsException e){
            System.out.println("未捕获异常");
        }
    }
}

第III章のカスタム例外

開発にはいくつかの例外が定義されていない、常にあるので、我々は彼らのビジネスの異常な状況に応じて例外クラスを定義する必要があります。

どのように異常なクラス定義:

  1. 継承されたコンパイラ例外をカスタマイズしますjava.lang.Exception

    内部コンパイラメソッドが例外をスローした場合は、例外を処理、またはスロー、またはしようとする必要があります...キャッチ

  2. ランタイム例外クラス、継承でjava.lang.RuntimeException

    ランタイム例外、治療せずに、仮想マシンの処理に(割込み処理)

/* 自定义一个异常类 */
class myException extends Exception{
    public myException(){}
    public myException(String s){
        super(s);
    }
}
public class 自定义异常类 {
    /* 定义抛出异常的方法 */
    public static String func(int score) throws myException {
        System.out.println("1");
        if (score >= 0 && score <= 100) {
            return "ok";
        } else {
            throw new myException("错误输入");
        }
    }
    public static void main(String[] args) {
        try{
            String str1 = func(88);
            System.out.println(str1);
            String str2 = func(120);
            System.out.println(str2);

        } catch (myException e){
            System.out.println("异常信息为:"+e.getMessage());
        } finally {
            System.out.println("不管上面代码出错否,都会出现这句话");
        }
    }
}

第IV章マルチス​​レッド

以上4.1スレッドの原則

継承Threadクラス、および実行機能にコードを配置して実行し、最終的に呼び出しを開始:マルチスレッドファッションを使用します

package day13;
class myThread extends Thread {
    private String testName;

    public myThread() {
    }

    public myThread(String testName) {
        this.testName = testName;
    }

    public String getTestName() {
        return testName;
    }

    public void setTestName(String testName) {
        this.testName = testName;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(testName+"-->"+i);
        }
    }
}
public class 多线程 {
    public static void main(String[] args) {
        myThread myThread = new myThread("吖啊");
        /* 以下语句执行后会开启一个不同于main线程的新线程 */
        myThread.start();// 调用start方法,
        for (int i = 0; i < 10; i++) {
            System.out.println("main-->"+i);
        }
    }
}

出力順序が一意ではありません

1567695362576

4.2 Threadクラス

次のように使用されたjava.lang.Threadクラス、

コンストラクタ:

  • public Thread():新しいスレッドオブジェクトを割り当てます
  • public Thread(String name):新しいスレッドオブジェクトの指定された名前を割り当て
  • public Thread(Runnable target)指定された目標を持つ新しいスレッドオブジェクトを割り当てます。
  • public Thread(Runnable target,String name)指定された対象物との新しいスレッドには名前が割り当てられています:

一般的な方法:

  • public String getName():現在のスレッドの名前を取得します。

  • public void start():実行を開始するには、このスレッドを引き起こす、Java仮想マシンは、このスレッドのrunメソッドを呼び出します

  • public void run():このスレッドのタスクが実行される、このカスタムコード

  • public static void sleep(long millis):スレッドが現在一時停止し、指定されたミリ秒数を実行しています

    ここでは例外、例外処理、または試しの必要性...キャッチ、またはスローがあるかもしれません

  • public static Thread currentThread():現在実行中のスレッドオブジェクト参照のリターン

(二つの方法で)スレッド名を取得します:

class MyThread extends Thread {
    @Override
    public void run() {
        /* 获取进程名方法一 */
        String name_1 = this.getName();
        System.out.println(name_1);
        /* 获取进程名方法二 */
        Thread thread = Thread.currentThread();
        System.out.println(thread);
        String name_2 = thread.getName();
        System.out.println(name_2);
    }
}
public class 获取线程名称 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        System.out.println(Thread.currentThread().getName());
    }
}

(2つの方法で)スレッド名を設定します。

  1. 使用のsetName Threadクラス。

    void setName(String name):変更は、このスレッドの名前を引数nameに等しく

  2. 子スレッドの名前を設定するには、親クラスとコール引数のコンストラクタ、親にスレッド名を渡し、その親クラス(スレッド);、パラメータ化コンストラクタメソッドを作成する引数のスレッドの名前を渡します。

class MyThread extends Thread {
    public MyThread() {
    }
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class 设置线程名称 {
    public static void main(String[] args) {
        MyThread myThread_1 = new MyThread();
        /* 方法一 */
        myThread_1.setName("使用setName方法定义的进程名称");
        myThread_1.start();
        /* 方法二 */
        MyThread myThread_2 = new MyThread("使用构造函数定义的进程名称");
        myThread_2.start();
    }
}
// 输出
// 使用setName方法定义的进程名称
// 使用构造函数定义的进程名称

マルチスレッドを作成するために、4.3第二の方法

実装手順:

  1. インタフェースRunnableを実装するクラスを作成
  2. runメソッドのRunnableインタフェースは、実装クラスに書き換えられたスレッドのタスクを設定します
  3. クラスを作成することが実装のRunnableインタフェースオブジェクト
  4. スレッドクラスオブジェクトのコンストラクターが渡され、Runnableインタフェースのクラスオブジェクトを実装作成
  5. Startメソッドは、runメソッド新しいスレッドの実行を開いて、Threadクラスと呼ばれています
/* 实现步骤1 */
class RunnableImpl implements Runnable {
    /* 实现步骤2 */
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class 多进程创建的方式二 {
    public static void main(String[] args) {
        /* 实现步骤3 */
        RunnableImpl runnable = new RunnableImpl();
        /* 实现步骤4-5 */
        new Thread(runnable).start();
    }
}

4.4スレッドとRunableの違い

リソース共有のためのThreadクラスからクラスの継承、適していない場合。あなたは、Runnableインタフェースを実装した場合でも、それは、共有リソースに簡単です。

要約すると、利点があるThreadクラスの継承よりもRunnableを実装します:

  1. 同じリソースを共有するために、同じプログラムコードのための複数のスレッド。
  2. Javaで単一継承の制限を回避するには、
  3. 操作デカップリング、プログラムの堅牢性を増加させる、コードが複数のスレッドで共有することができ、独立したコードを通します。
  4. 直接ではなく、継承のThreadクラスに、スレッドプールにのみ、このようなスレッドなどのRunnableまたは呼び出し可能なクラスを達成することができます置きます。

拡張:のJava、プログラムは、少なくとも二つのスレッドを実行するために起動するたびに、1はメインスレッド、ガベージコレクションスレッドです。コマンドは、Javaクラスを使用して実行されるたびに、実際には、JVMを開始しますので、各JVMは、実際のオペレーティングシステムのプロセスを開始しています。

スレッドの作成を達成するために、4.5匿名内部クラスの方法

public class 匿名类实现多线程 {
    public static void main(String[] args) {
        /* 继承Thread的匿名函数实现多线程 */
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        };
        thread.start();
        /* 接口Runnable使用多态实现多线程 */
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        };
        new Thread(runnable).start();
    }
}

第V章スレッド安全性の問題

5.1同期ブロック

synchronized領域キーワードのみ、このブロックのリソースへの相互排他的アクセスを強制表現する方法で使用することができます。

フォーマット:

synchronized(obj){
    // 需要同步操作的代码区域
}

ゲンロック(OBJ):

これは、OBJロックされている同期モニタを、と呼ばれる原則は、:現在のスレッドが実行同期ブロックを開始し、最初の同期コードブロックのロックを取得する必要があります。同期コードブロック終了つのみのスレッドが、モニターの同期を得ることができ、いつでもロック、スレッドは、同期モニタのロックを解除します。

ロックは、非静的メソッドであってもよく、前記静的メソッドで、現在のクラス自体(例えば、単一のアイドラ実施形態:Singleton.class)として、これです。

  1. ロックオブジェクトは、任意のデータ型を指定できます。
  2. 複数のスレッドのオブジェクトは、同じロックを使用する必要があります。

注:いずれかの時点で、最大で1つのスレッドが同期ロックを所有することができ、コードブロック(もに持って来られたと同時にロック)を入力するためのロックを持って、我々は他のスレッドが唯一のロック(ブロック)を待つことはできません発見しました。

彼は同期ブロックに来るまで、ロックを運ぶ誰でもCPUをつかんで誰が見て、この時間は、CPUリソースを得るためにはいくつかのプロセス、あなたが同期ブロックを実行した後、他のプロセスが、状態に入るようにブロックされている一方で、プロセスはまだまで、CPUリソースを持っているが次の同期コードブロック(またはコードの実行終了)へのサイクルは、CPUリソースを解放し、各ポストのための競争し、再度同期ブロックの次のラウンドを完了するために、プロセスのCPUリソースをブロック目を覚ますだろう。

例えば:

class sailTicket implements Runnable {
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"one");
        while (true) {
            System.out.println(Thread.currentThread().getName()+"two");
            /* 同步代码区,其中obj也可以换成this或者sailTicket.class */
            synchronized(obj){
                System.out.println(Thread.currentThread().getName()+"three");
                if (ticket > 0) {
                    System.out.println("正在售卖第" + ticket + "张票" + Thread.currentThread().getName());
                    ticket--;
                }
            }
        }
    }
}

public class 卖票的同步出售 {
    public static void main(String[] args) {
        sailTicket sailTicket = new sailTicket();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
    }
}
/* 部分输出结果如下:
Thread-2one
Thread-1one
Thread-0one
Thread-2two
Thread-1two
Thread-0two
Thread-2three
正在售卖第100张票Thread-2
Thread-2two
Thread-0three
正在售卖第99张票Thread-0
Thread-0two
Thread-1three
正在售卖第98张票Thread-1
Thread-1two
Thread-0three
正在售卖第97张票Thread-0
Thread-0two
Thread-2three
*/

5.2同期方式

使用してsynchronized実行のスレッド、他のスレッドが唯一の方法を待つことができたときにスレッドを確実にするために、同期メソッドを呼び出した修正方法を、

フォーマット:

public synchronized void method(){
    // 可能会产生线程安全问题的代码
}

同期ロックは誰ですか?

非静的メソッドの場合、ゲンロックはこれです、

静的メソッドのために、我々は、同期ロック現在バイトコードオブジェクトクラスのメソッド(クラス名の.class)を使用し

例えば:

class sailTicket implements Runnable {
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"one");
        while (true) {
            System.out.println(Thread.currentThread().getName()+"two");
            /* 执行同步方法 */
            method();
        }
    }
    public synchronized void method(){
        System.out.println(Thread.currentThread().getName()+"three");
        if (ticket > 0) {
            System.out.println("正在售卖第" + ticket + "张票" + Thread.currentThread().getName());
            ticket--;
        }
    }
}

public class 卖票的同步出售 {
    public static void main(String[] args) {
        sailTicket sailTicket = new sailTicket();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
    }
}
/* 部分输出结果如下:
Thread-1one
Thread-0one
Thread-2one
Thread-1two
Thread-0two
Thread-2two
Thread-1three
正在售卖第100张票Thread-1
Thread-1two
Thread-2three
正在售卖第99张票Thread-2
Thread-2two
Thread-0three
正在售卖第98张票Thread-0
Thread-0two
*/

5.3ロックロック

java.unit.concurrent.locks.Lockよりメカニズムを提供する同期コードブロック同期方法より広いロック動作、シンクブロック/同期方法は、より強力に加えて、ロックが有する機能を持つオブジェクト指向の実施形態です。

次のようにロックロックロックは、ロックおよびロック解除する方法であって、同期と呼ばれます。

  • public void lock():プラスゲンロック
  • public void unlock:同期ロック解除

例えば:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class sailTicket implements Runnable {
    private static int ticket = 100;
    public Lock lock = new ReentrantLock();
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"one");
        while (true) {
            System.out.println(Thread.currentThread().getName()+"two");
            /* 加同步锁 */
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+"three");
                if (ticket > 0) {
                    System.out.println("正在售卖第" + ticket + "张票" + Thread.currentThread().getName());
                    ticket--;
                }
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                /* 不管是否有错误,都会释放同步锁 */
                lock.unlock();
            }
        }
    }
    public static synchronized void method(){

    }
}

public class 卖票的同步出售 {
    public static void main(String[] args) {
        sailTicket sailTicket = new sailTicket();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
        new Thread(sailTicket).start();
    }
}

第VI章のスレッドプール

スレッドプール:JDK1.5は後に解決してスペースの無駄、頻繁に、時間もたらした破壊を作成するために、スレッドを

Java.util.concurrent.Executors:スレッドプールを生成するためのスレッドプールのクラスファクトリ

エグゼキュータクラスの静的メソッド:

static ExecutorService newFixedThreadPool(int nThreads):スレッドの固定数は、再利用可能なスレッドプールを作成します

パラメータ:

int型にnthreadsを:含まれるスレッドプール内のスレッドの数を作成します。

戻り値:

ExecutorServiceのインタフェースは、クラスオブジェクトはExecutorServiceのインタフェースを実装戻り、我々はExecutorServiceの(指向プログラミング・インタフェース)を受信するインターフェイスを使用することができ

Java.util.concurrent.ExecutorService:スレッドプールからスレッドを取得するために、スレッドプールインターフェース、startメソッドが呼び出されると、タスクの実行スレッド

一般的な方法:

submit(Runnable task):実行用のRunnableタスクを送信

void shutdown():クローズ/スレッドプールを破壊します

ステップを使用して、プールのスレッド:

  1. スレッドプールのスレッドの静的メソッド指定された数を生成するファクトリクラスキュータnewFixedThreadPool内部スレッドプールを使用します。
  2. 実装、Runnableインタフェースはrunメソッドをオーバーライドすることをクラスを作成し、スレッドのタスクを設定します。
  3. ネジ付きタスク(Runnableを実装クラス)、オープンスレッド、runメソッドを渡し、ExecutorServiceの中にメソッド呼び出しを提出します。
  4. スレッドプールの破壊でExecutorServiceのシャットダウンメソッドの呼び出し。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/* 创建Runnable的实现类,并重写run方法 */
class RunnableImpl implements Runnable {
    private int num = 20;
    @Override
    public void run() {
        while (num > 0){
            System.out.println("this is:" + num + Thread.currentThread().getName());
            num--;
        }
    }
}
public class 使用线程池 {
    public static void main(String[] args) {
        /* 生成线程数为3的线程池 */
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        /* Runnable实现类的对象实例 */
        RunnableImpl runnable = new RunnableImpl();
        /* 将runnable作为参数传入线程池的submit方法中,从而获取一个线程执行run任务
         * 若是任务完成或者分配的时间片使用完毕,则自动将线程归还给线程池
         */
        executorService.submit(runnable);
        executorService.submit(runnable);
        executorService.submit(runnable);
    }
}

第VII章ラムダ式

匿名内部クラスを書くの簡単な方法

ラムダは、前提を使用します。

  • ラムダを使用すると、インターフェイス、および必要なインターフェイス持っている必要がありますし、唯一の抽象メソッドを。

    JDK内蔵かどうかはRunnableComparatorインターフェイスまたはカスタムインタフェース、および抽象インタフェースのメソッドとする場合にのみがある場合にのみ、使用することができますラムダ。

  • ラムダを使用することでなければならない、推論文脈

    この方法は、ローカル変数または引数型がラムダを例にインターフェイスを使用することができ、ラムダに対応するインターフェイスタイプでなければなりません。

標準形式のラムダ式は、3つの部分から構成します:

  1. いくつかの引数:抽象インタフェースのプロセスパラメータ、引数なしで、それが空である、書込みパラメータのパラメータがあり、パラメータのコンマ複数の分離。

    括弧内のデータタイプパラメータリスト、省略することができ、唯一のパラメータ場合、タイプ及び()を省略することができます

  2. 矢印:移送手段のメソッドに渡されたパラメータ{01}。
  3. コードの一部:抽象インタフェースメソッドを書き換えます。

{}コードで唯一の行が、戻り値か否かを三ながら省略しなければならない({}、リターン、セミコロン)を省略することができる場合

フォーマット:

(パラメータリスト) - >(いくつかのコード書き換え方法)

例I:

public class 使用Lambda表达式 {
    public static void main(String[] args) {
        /* 使用匿名内部类开启多线程 */
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "这个匿名内部类执行了");
            }
        }).start();
        /* 使用Lambda开启多线程 */
        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "Lambda表达式执行了");
        }).start();
        /* 优化Lambda书写方式 */
        new Thread(()-> System.out.println(Thread.currentThread().getName() + "优化版Lambda表达式执行了")).start();
    }
}
/*  输出结果如下:
    Thread-2优化版Lambda表达式执行了
    Thread-0这个匿名内部类执行了
    Thread-1Lambda表达式执行了
*/

例II:

import java.util.Arrays;
import java.util.Comparator;

class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class 使用Lambda进行排序 {
    public static void main(String[] args) {
        Person[] personArr = {
                new Person("张三",19),
                new Person("李四",17),
                new Person("王五",22)
        };
        /* 方式一:使用匿名内部类排序 */
        Arrays.sort(personArr, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        for (Person item : personArr) {
            System.out.println(item);
        }
        /* 方式二:使用Lambda表达式排序,其中参数列表的数据类型Person可以省略 */
        Arrays.sort(personArr, (Person o1, Person o2) -> {
                return o1.getAge() - o2.getAge();
            }
        );
        System.out.println("===========================");
        for (Person item : personArr) {
            System.out.println(item);
        }
    }
}
/*  输出结果如下:
    Person{name='张三', age=19}
    Person{name='李四', age=17}
    Person{name='王五', age=22}
    ===========================
    Person{name='李四', age=17}
    Person{name='张三', age=19}
    Person{name='王五', age=22}
*/

おすすめ

転載: www.cnblogs.com/carle/p/12095376.html