Runnable in Java with Examples - Java 147

Runnable in Java with Examples – Java 147

Runnable in Java with Examples

有兩種方法可以啟動一個新執行緒,實作 Runnable Interface 或繼承 Thread ,覆寫 run 方法, Thread 有一個接受 Runnable 的建構子,將實現者傳給 Thread ,然後調用 start 建立一個新執行緒,此緒會執行 run 中的程式碼, Runnable in Java 本篇增加了範例,並透過單元測試來驗證產出結果。

檔案目錄

./
   +- src
       +- test
       |   +- org
       |       +- ruoxue
       |           +- java_147
       |               +- multithreading
       |                   +- runnable
       |                       +- RunnableWithExamplesTest.java   

單元測試

Runnable Java 提供執行、拋出例外等操作。

task

Java Runnable 可使用繼承 Thread 覆寫 run 方法,建立 3 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成,主執行緒等待 3 秒才結束任務。

	protected class Task extends Thread {

		private int id;

		public Task(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void task() {
		try {
			int taskSize = 3;
			for (int i = 0; i < taskSize; i++) {
				Thread thread = new Thread(new Task(i));
				thread.start();
			}
			TimeUnit.SECONDS.sleep(3);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
2023/02/06 03:18:44 T[12] worker: 0 ready
2023/02/06 03:18:44 T[16] worker: 2 ready
2023/02/06 03:18:44 T[14] worker: 1 ready
2023/02/06 03:18:45 T[12] worker: 0 finished
2023/02/06 03:18:45 T[16] worker: 2 finished
2023/02/06 03:18:45 T[14] worker: 1 finished

worker

Java Runnable 也可使用實作 Runnable Interface 的 run 方法,建立 3 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成,調用 join 讓主執行緒等待 3 條執行緒全部完成才結束任務。

	protected class Worker implements Runnable {

		private int id;

		public Worker(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void worker() {
		int taskSize = 3;
		List<Thread> threads = new ArrayList<Thread>();
		IntStream.range(0, taskSize).forEach(e -> {
			Thread thread = new Thread(new Worker(e));
			thread.start();
			threads.add(thread);
		});

		threads.forEach(e -> {
			try {
				e.join();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		});
	}
2023/02/06 03:19:33 T[12] worker: 1 ready
2023/02/06 03:19:33 T[11] worker: 0 ready
2023/02/06 03:19:33 T[13] worker: 2 ready
2023/02/06 03:19:34 T[13] worker: 2 finished
2023/02/06 03:19:34 T[12] worker: 1 finished
2023/02/06 03:19:34 T[11] worker: 0 finished

brokenWorker

Runnable Java 建立 3 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成,其中 1 條執行緒拋出例外,調用 join 讓主執行緒等待 3 條執行緒全部完成才結束任務。

	protected class BrokenWorker implements Runnable {

		private int id;

		public BrokenWorker(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				if (id == 1) {
					throw new RuntimeException("BrokenWorker " + id + " throw exception");
				}
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void brokenWorker() {
		int taskSize = 3;
		AtomicInteger ids = new AtomicInteger();
		List<Thread> threads = Stream.generate(() -> new Thread(new BrokenWorker(ids.getAndIncrement())))
				.limit(taskSize).collect(Collectors.toList());
		threads.forEach(e -> e.start());

		threads.forEach(e -> {
			try {
				e.join();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		});
	}
java.io.IOException: BrokenWorker 1 throw exception
	at org.ruoxue.java_147.multithreading.RunnableWithExamplesTest$BrokenWorker.run(RunnableWithExamplesTest.java:110)
	at java.lang.Thread.run(Thread.java:750)
2023/02/06 03:23:24 T[11] worker: 0 ready
2023/02/06 03:23:24 T[13] worker: 2 ready
2023/02/06 03:23:25 T[11] worker: 0 finished
2023/02/06 03:23:25 T[13] worker: 2 finished

RunnableWithExamplesTest.java

Java Runnable 新增單元測試,驗證是否符合預期。

package org.ruoxue.java_147.multithreading.runnable;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.junit.Test;

public class RunnableWithExamplesTest {

	protected class Task extends Thread {

		private int id;

		public Task(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void task() {
		try {
			int taskSize = 3;
			for (int i = 0; i < taskSize; i++) {
				Thread thread = new Thread(new Task(i));
				thread.start();
			}
			TimeUnit.SECONDS.sleep(3);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	protected class Worker implements Runnable {

		private int id;

		public Worker(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void worker() {
		int taskSize = 3;
		List<Thread> threads = new ArrayList<Thread>();
		IntStream.range(0, taskSize).forEach(e -> {
			Thread thread = new Thread(new Worker(e));
			thread.start();
			threads.add(thread);
		});

		threads.forEach(e -> {
			try {
				e.join();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		});
	}

	protected class BrokenWorker implements Runnable {

		private int id;

		public BrokenWorker(int id) {
			this.id = id;
		}

		@Override
		public void run() {
			try {
				if (id == 1) {
					throw new RuntimeException("BrokenWorker " + id + " throw exception");
				}
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				System.out.println(
						sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
				TimeUnit.SECONDS.sleep(1);
				System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id
						+ " finished");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	@Test
	public void brokenWorker() {
		int taskSize = 3;
		AtomicInteger ids = new AtomicInteger();
		List<Thread> threads = Stream.generate(() -> new Thread(new BrokenWorker(ids.getAndIncrement())))
				.limit(taskSize).collect(Collectors.toList());
		threads.forEach(e -> e.start());

		threads.forEach(e -> {
			try {
				e.join();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		});
	}
}

心得分享

Runnable in Java Multithreading 多執行緒一直以來,都是 Java 的主要方面,提供建立新執行緒,執行指定任務,使用 Java Runnable 不能拋出設計階段的檢查例外,像是: FileNotFoundException ,但是可以拋出執行階段的執行例外,如: RuntimeException ,多執行緒程式包含兩個或多個可以並發執行的部分,每個部分可以同時處理不同的任務,Runnable Java 進而優化利用可用資源。

發佈留言