例外処理の基本
finallyブロックの重要性:tryブロック内で例外が発生するかどうか、あるいはcatchブロックで例外が捕捉されるかどうかに関わらず、finallyブロック内のコードは常に実行されます。
マルチスレッドの実装方法
Threadクラスを継承する方法
public class ThreadDemo extends Thread {
public static void main(String[] args) {
ThreadDemo worker = new ThreadDemo("ワーカースレッド");
worker.start();
Thread.currentThread().setName("メインスレッド");
for (int count = 0; count < 10; count++) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + count);
}
}
public ThreadDemo() {}
public ThreadDemo(String threadName) {
super(threadName);
}
@Override
public void run() {
for (int count = 0; count < 10; count++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(getName() + ":" + count);
}
}
}
Runnableインターフェースを実装する方法
public class TaskExecutor implements Runnable {
public static void main(String[] args) {
Runnable task = new TaskExecutor();
Thread workerThread = new Thread(task);
workerThread.start();
for (int count = 0; count < 10; count++) {
System.out.println("メインスレッド:" + count);
}
}
@Override
public void run() {
for (int count = 0; count < 10; count++) {
System.out.println("サブスレッド:" + count);
}
}
}
注意:継承は単一継承しかできないため、インターフェース実装方式が推奨されます。
匿名内部クラスを使用する方法
public class AnonymousThreadDemo {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}).start();
}
}
スレッドセーフティの実現
同期ブロックの使用
public class SharedResource implements Runnable {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
new Thread(resource).start();
new Thread(resource).start();
new Thread(resource).start();
}
private int counter = 10;
private final Object lock = new Object();
@Override
public void run() {
while (true) {
synchronized (lock) {
if (counter > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + counter);
counter--;
}
}
}
}
}
同期メソッドの使用
public class SynchronizedMethod implements Runnable {
public static void main(String[] args) {
SynchronizedMethod instance = new SynchronizedMethod();
new Thread(instance).start();
new Thread(instance).start();
new Thread(instance).start();
}
private int counter = 10;
@Override
public void run() {
while (true) {
processResource();
}
}
public synchronized void processResource() {
if (counter > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + counter);
counter--;
}
}
}
静的同期メソッドの使用
public class StaticSyncMethod implements Runnable {
public static void main(String[] args) {
StaticSyncMethod instance = new StaticSyncMethod();
new Thread(instance).start();
new Thread(instance).start();
new Thread(instance).start();
}
private static int counter = 10;
@Override
public void run() {
while (true) {
processStaticResource();
}
}
public static synchronized void processStaticResource() {
if (counter > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + counter);
counter--;
}
}
}
スレッド状態とプロデューサー/コンシューマーパターン
public class ProducerConsumerDemo {
public static void main(String[] args) {
Object monitor = new Object();
// プロデューサースレッド
new Thread() {
@Override
public void run() {
synchronized (monitor) {
try {
monitor.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("プロデューサー:製品生産開始");
for (int time = 0; time < 3; time++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println((time + 1) + "秒経過");
}
System.out.println("プロデューサー:製品生産完了");
monitor.notify();
}
}
}.start();
// コンシューマースレッド
new Thread() {
@Override
public void run() {
synchronized (monitor) {
System.out.println("コンシューマー:製品を要求、生産待機中");
monitor.notify();
try {
monitor.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("コンシューマー:製品使用開始");
}
}
}.start();
}
}
スレッドプールの活用
public class ThreadPoolExample implements Runnable {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
threadPool.submit(new ThreadPoolExample());
threadPool.submit(new ThreadPoolExample());
threadPool.submit(new ThreadPoolExample());
threadPool.shutdown();
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "がタスクを実行中");
}
}