マルチスレッド化
スレッドは、プロセス (プロセス、実行中のプログラムのインスタンス) 内の単一の連続した制御フローです。複数のスレッド間の共有メモリは、同じプロセスの異なる「ブランチ」です。
「マルチスレッド」とは、プログラム内で複数のスレッドを開始することを意味します。これは、「並列」で実行される複数のタスクとして現れます。
新しいスレッドの開始
まず、開始する新しいスレッドを Thread クラスの run() メソッドに置く必要があります。このクラスを作成するには 2 つの方法があります。
Thread クラスのサブクラスを作成します。
Runnable インターフェイスを実装します。より一般的に使用される理由:
タスクと実行の分離。
マルチスレッドのリソース共有の実装が容易になります。
単一継承の制限を回避します。
次に、このクラスの start() メソッドを呼び出すと、すぐに戻り、同時にスレッドが実行を開始します。その run() メソッドを直接呼び出すことはできません。
// 最初にクラスを作成し、Runnable インターフェイスを実装します
class MyThreadimplements Runnable { // 実行することを run() メソッドに入れます @Override public void run() { // 何かを実行します } public MyThread() { super( ); } } // オブジェクトをインスタンス化し、スレッドを開始します t = new MyThread(); t.start(); Java 8 以降、ラムダ式は次のように省略できます。
Thread t = new Thread(() -> { // do something }); t.start();スレッドの停止スレッドは自発的に停止できます。
run() メソッドは正常に終了し、スレッドは自然に終了します。
run() メソッドで例外が発生しましたが、キャッチされず、スレッドが予期せず終了しました。
スレッドの stop() メソッドを呼び出すことで、スレッドを外部から終了できます。安全ではなく、時代遅れです。
スレッドの状態
Java のスレッドには 5 つの状態があります。
新しいステータス NEW、スレッド作成のステータスですが、start() はありません。
実行可能状態 RUNNABLE、スレッドは開始されました。
準備完了状態 READY、スレッドはリソースを待っています。
実行状態は RUNNING で、スレッドは実行するためのリソースを占有しています。
ブロック状態 BLOCKED は、同期またはロックが発生し、対応するロックを取得できない場合に、この状態に入ります。
待機状態 WAITING。現在のスレッドが Object.wait() を呼び出すか、他のスレッドが Thread.join() を呼び出し、時間が設定されていない場合、待機状態に入ります。
Thread.join() を呼び出したスレッドが終了するか、Object.notify() または Object.notifyAll() を呼び出して待機中のスレッドがウェイクアップされると、スレッドは実行可能な状態に戻ります。
時間指定待機状態 TIMED_WAITING は、現在のスレッドが Thread.sleep(time) を呼び出すか、現在のスレッドが Object.wait(time) を呼び出すか、他のスレッドが Thread.join(time) を呼び出すと、この状態に入ります。
タイマーが期限切れになると、スレッドは実行可能な状態に戻ります。
停止状態 TERMINATED、スレッドは停止しました。
スレッドの割り込み スレッド
で割り込み() メソッドを呼び出すと、スレッドの割り込みフラグが true に設定されます。スレッドは、この割り込みを独自に処理するかどうかを決定できます。
同期とデッドロック
Java でオブジェクトをロックするには、synchronized キーワードを使用します。ロック後、このオブジェクトはロックが解除されるまで現在のスレッドによって排他的に所有されます。
クラスカウンター { public static int count = 0; }
/** 特定のスレッドの run() メソッド**/
for (int i = 0; i < 100; i++) { synchronized (Counter.lock) { // ロックを取得 // JVM は実行中にそれを保証しますここのコードでは、Counter は他のスレッドによって変更されません Counter.lock++; } // Unlock }複数のスレッドがロックを取得する順序が一貫していない場合、「デッドロック」が発生する可能性があります。 A をロック、私は B をロック、私は A を取得できません、あなたは B を取得できません」膠着状態。デッドロックは、スレッドがロックを取得する順序を制御することで回避できます。
生産者消費者モデル
![無題](%E5%A4%9A%E7%BA%BF%E7%A8%8B%E3%80%81%E6%B3%9B%E5%9E%8B%E4% B8% 8E%E5%8F%8D%E5%B0%84%206e572eeb16b3446893407c2aefcd0d6b/無題.png)
ジェネリック
ジェネリックを使用すると、クラス/メソッド/インターフェイスをさまざまなデータ型に対して再利用できるため、コードの再利用が向上します。
ジェネリック クラス
ジェネリック クラスは、1 つ以上のジェネリック変数を持つクラスです。
class Generic<T> { // このクラスのジェネリック T を宣言します
// これで、T は Integer および String と同じデータ型と見なすことができます
public T t;
public Generic() { ... }
public Generic(T t ) { ... }
public void func1(T t) { ... }
public T func1() { ... }
}
新しいジェネリック クラスを作成するときに使用する特定の型を指定する必要があります。
// 基本的なデータ型はジェネリック クラスでは使用できないという事実に特に注意してください。つまり、int は使用できず、Integer
Generic<Integer> g1 = new Generic<>();
g1.t = 114514; //問題ありません
g1.t = "114514"; // 大きな問題
ジェネリック クラスは複数のジェネリックを導入する可能性があります。
class Generic<T, E> { ... }ジェネリック
メソッド ジェネリック
メソッドは、1 つ以上のジェネリック変数を持つメソッドです。通常のクラスまたはジェネリック クラスで定義できます。ジェネリック クラスでジェネリック変数を使用するメソッド (上記の func1(T t) など) はジェネリック メソッドではなく、ジェネリック型を宣言するメソッドのみが「ジェネリック メソッド」となります。
class GenericFunction { public <T, E> void func(T t, E e) { ... } public <T> T func2() { ... } }ジェネリック メソッドを呼び出す場合、メソッドを指定する必要はありません。メソッド名の前にジェネリック関数 特定の型の型。
GenericFunction g = new GenericFunction();
g.<Integer, String>func(123, "123");
g.func2("hi");
静的ジェネリック メソッドがジェネリック クラスに出現する場合、ジェネリック クラスを使用したジェネリックはできません。 。
ジェネリック インターフェイス
インターフェイスにはジェネリック タイプを持つこともできます。ジェネリック インターフェイスを実装する場合、実装されるクラスはジェネリック クラスまたは非ジェネリック クラスのいずれかになります。
インターフェイス Addable <T> { public T add(T a, T b); }
// 非ジェネリック クラスとして実装する場合は、ジェネリック
クラスの具象型を指定します Intimplements Addable<Integer> { @Override public Integer add(Integer a, Integer b) { return a + b; } }
// ジェネリック クラスとして実装する場合、一貫性がなければなりません
// V---------------------V
class Number<T> は Addable<T> を実装します { @ Override public T add(T a, T b) { ... } }ワイルドカードジェネリックでは、クラス間の継承関係が考慮されません。つまり、Integer は Object のサブクラスですが、List<Integer> を仮パラメータ List<Object> に置き換えることはできません。
// メソッドの宣言
void func(List<Object> list) { ... }
List<Integer> intList = ...;
func(intList); // 大きな問題があり、エラーが報告されます。
これに応じて、汎用のワイルドカードを使用する必要があります。
<?> は任意の型と一致します。
<? extends class> は、クラス class とそのすべてのサブクラスに一致します。
<? super class> は、クラス class とそのすべてのスーパークラスに一致します。
ワイルドカードは仮パラメータとコード呼び出しにのみ使用でき、クラスやジェネリック メソッドの定義には使用できません。
public void func(List<? extends Number> list) { ... } // 問題なし
public <? extends Number> void func(List<?> list) { ... } // 大きな問題
反射
Class クラス
Class クラスは「クラスのクラス」、Class オブジェクトは「クラスの型オブジェクト」と呼ばれ、各クラスがインスタンス化されるときに JVM によって生成されます。
Student hans = new Student("Hans", 19); // Student オブジェクトを作成します
System.out.println(hans.getClass()); // クラスを印刷します Student
System.out.println(hans.getClass().getName ()); // Print Student
上の例は、任意のオブジェクトで getClass() メソッドを使用すると、そのクラスの型オブジェクトを取得できることを示しています。さらに、このメソッドを使用して、「クラス名」に従ってクラスの型オブジェクトを取得することもできます。
Class cl = Class.forName("Student"); // forName() 静的メソッドで Student という名前のクラスを検索します。 System.out.println(cl); // forName() 静的メソッドが見つからない場合は、
クラス Student を出力します。
対応するクラスは ClassNotFoundException 例外をスローします。
リフレクションを使用してクラスのインスタンスを作成するには
、Class.newInstance() を使用します。
Class cl = Class.forName("Date"); // Date クラスの型オブジェクトを取得します
Date date = cl.newInstance()
これは、クラスのデフォルトのコンストラクター (パラメーターなし) を呼び出します。
まず Constructor を使用してクラスのコンストラクターを取得し、それを呼び出します。
// すべての「パブリック」コンストラクターを取得します
public Constructor[] getConstructors() {}
// すべてのコンストラクターを取得します
public Constructor[] getDeclaredConstructors() {}
// 指定された型の「パブリック」コンストラクターを取得します
public Constructor getConstructor (Class ...) {}
// 指定された型のすべてのコンストラクターを取得します
public Constructor getDeclaredConstructor(Class ...) {}
例:
public class Student { private 文字列名; public Student() { ... } // 1 public Student(String name) { ... } // 2 }
クラス StudentClass = Class.forName("Student");
Constructor con = StudentClass.getConstructor(String.class) // 会获得 2
Constructor[] cons = StudentClass.getConstructors(); // 会获得 1 と 2
Student stu = (Student) con.newInstance("Hans"); // newInstance() を呼び出してインスタンスを作成します リフレクションを
使用してメンバー変数を取得および変更します
リフレクションを通じて、オブジェクト内の任意のフィールドの値を取得および変更できます。このフィールドがパブリックかどうか。
// すべてのパブリック フィールドを取得
public Field[] getFields() {}
// すべてのフィールドを取得
public Field[] getDeclaredFields() {}
// 指定された名前のパブリック フィールドを取得
public Field getField(String name) {} //
Get指定された名前のフィールド
public Field getDeclaredField(String name) {}
// フィールドの値を取得します
Field.get(Object object)
// フィールドの値を変更します
Field.set(Object object, Object value)
例
Student hans = new Student("Hans", 19);
// Student クラスの型クラスを取得します Class
StudentClass = hans.getClass();
// Student クラスの name フィールドを取得します
Field f =studentClass.getDeclaredField(" name");
// Student オブジェクトの name フィールドの値を取得します hans
f.setAccessable();
String hansName = (String) f.get(hans);
// Student オブジェクトの name フィールドの値を変更しますhans
f.set(hans, "Hans WAN ");
リフレクションを使用してメンバー メソッドを取得する パブリック
であるかどうかに関係なく、リフレクションを通じてオブジェクト内の任意のメソッドを取得できます。
// すべてのパブリック メソッドを取得します
public Method[] getMethods() {}
// パブリックかどうかに関係なく、すべてのメンバー メソッドを取得します
public Method[] getDeclaredMethods() {}
// 指定されたメソッド名とパラメータ型を持つメソッドを取得します
public Method[ ] getMethod(文字列名, クラス...) {}
// 取得したメソッドを呼び出す
Method.invoke(Object object, Object ...)
たとえば
Student hans = new Student("Hans", 19);
メソッド m = Student.class.getMethod("getName", String.class, Integer.class);
文字列 hansName = (文字列) m.invoke(hans);