實現Runnable接口--策略模式的應用

前言

實現Runnable接口是啓動多線程最常見的方式, 而這個過程中我們實則使用了策略模式

策略模式UML圖

在這裏插入圖片描述
策略模式有以上角色: 抽象策略(Strategy)), 具體策略, 環境上下文(Context), 其中Context角色依賴Strategy

一個策略模式案例

@FunctionalInterface
// Strategy角色, 也是函數式接口
public interface Strategy {
	double calculate(double salary, double bonus);
}
// Context 上下文環境, 依賴Strategy
public class TaxCalculator {
	// 工資
	private final double salary;
	// 獎金
	private final double bonus;
	// 計稅策略
	private Strategy strategy;

	public TaxCalculator(double salary, double bonus, Strategy strategy) {
		this.salary = salary;
		this.bonus = bonus;
		this.strategy = strategy;
	}

	public double getSalary() {
		return salary;
	}

	public double getBonus() {
		return bonus;
	}

	protected double calculate(){
		return strategy.calculate(salary,bonus);
	}
}
// 測試類, 用Lambda表達式表示具體策略實例
public class Test {
	public static void main(String[] args) {
		TaxCalculator calculator1 = new TaxCalculator(10000d, 2000d,
				(salary, bonus) -> salary * 0.1 + bonus * 0.15);
		TaxCalculator calculator2 = new TaxCalculator(15000d, 4000d,
				(salary, bonus) -> salary * 0.15 + bonus * 0.20);
		System.out.println(calculator1.calculate());
		System.out.println(calculator2.calculate());
	}
}

一個實現Runnable接口啓動多線程的實例

// Runnable就是抽象策略接口, 本類就是具體策略類, run() 方法封裝了具體實現
public class TicketWindowRunnable implements Runnable {
	private int index = 1;
	private final static int MAX = 1000;

	public void run() {
		while (index <= MAX){
			System.out.println(Thread.currentThread() + "的號碼是" + (index++));
			try {
				Thread.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
// 模擬銀行櫃檯叫號, Thread類可對照策略模式中的 Context角色
public class Bank2 {
	public static void main(String[] args) {
		final TicketWindowRunnable ticketWindow = new TicketWindowRunnable();
		// 依賴具體Strategy 角色
		Thread t1 = new Thread(ticketWindow,"1號窗口");
		Thread t2 = new Thread(ticketWindow,"2號窗口");
		Thread t3 = new Thread(ticketWindow,"3號窗口");

		t1.start();
		t2.start();
		t3.start();
	}
}
// 參考Thread類的start()方法源碼, 着重關注 start0() 方法
public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        boolean started = false;
        try {
            start0();		// 這是個native方法, 會調用具體策略中的 run() 方法, 並開啓線程
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }

總結

與策略模式做類比可以更好地理解通過實現Runnable接口啓動多線程的寫法

把Thread類看做Context上下文角色, Runnable接口看做抽象策略角色, 而具體策略角色由開發者自己定義(也就是重寫run方法)

開啓多線程的方法: new Thread(Runnable runnable, String name). start(), 對照Context角色依賴Strategy角色的方式就很好理解了

發佈了18 篇原創文章 · 獲贊 3 · 訪問量 1047
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章