Java では、マルチスレッドを実装する方法がいくつかあります。一般的な方法をいくつか示します。
1. Threadクラスを継承する
Thread クラスから継承するサブクラスを作成し、その run() メソッドをオーバーライドして、スレッドによって実行されるタスクを定義できます。このサブクラスのインスタンスを作成し、start() メソッドを呼び出すことで、スレッドを開始できます。
class MyThread extends Thread {
public void run() {
// 线程执行的任务
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
2. Runnableインターフェイスを実装する
Runnable インターフェイスを実装し、その run() メソッドを実装してスレッドのタスクを定義できます。次に、Thread クラスのインスタンスを作成し、Runnable オブジェクトをパラメータとして Thread コンストラクターに渡すことによって、スレッドを開始できます。
class MyRunnable implements Runnable {
public void run() {
// 线程执行的任务
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
3. Callable と Future の使用
Callable は、スレッドのタスクを定義するために実装できる戻り値を持つインターフェイスです。Executor フレームワークの submit() メソッドを使用して、Callable タスクを送信し、タスクの実行結果を取得できる Future オブジェクトを取得します。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<Integer> {
public Integer call() {
// 线程执行的任务,并返回结果
return 42;
}
}
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
MyCallable callable = new MyCallable();
Future<Integer> future = executor.submit(callable);
try {
Integer result = future.get();
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdown();
}
}
スレッド セーフとは、マルチスレッド環境で複数のスレッドが共有リソースに同時にアクセスするときに、データの正確性と一貫性を確保することを指します。スレッド セーフ コードは、データの破損や不整合を引き起こすことなく、複数のスレッド間の競合状態を正しく処理します。
スレッドセーフを実現するには、いくつかのアプローチがあります。
1. 同期メカニズム (synchronized キーワードや Lock インターフェイスなど) を使用して共有リソースへのアクセスを制御し、同時に 1 つのスレッドのみが重要なコード セグメントにアクセスできるようにします。
2. アトミック操作クラス (AtomicInteger、AtomicLong など) を使用してアトミック操作を実行します。これらのクラスは、競合状態を回避するためのスレッドセーフな操作メソッドを提供します。
3. HashMap の代わりに ConcurrentHashMap を使用する、ArrayList の代わりに CopyOnWriteArrayList を使用するなど、スレッドセーフなデータ構造を使用します。
スレッドセーフであるということは、プログラムがクラッシュしない、またはエラーが発生しないということだけを意味するわけではないことに注意することが重要です。また、データの一貫性と正確性を確保し、デッドロック、ライブロック、競合状態などの潜在的な同時実行の問題を回避する必要もあります。したがって、マルチスレッド コードを作成する場合は、スレッドの安全性を確保することが非常に重要です。