欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现Runnable接口--策略模式的应用

程序员文章站 2022-05-26 07:49:55
...

前言

实现Runnable接口是启动多线程最常见的方式, 而这个过程中我们实则使用了策略模式

策略模式UML图

实现Runnable接口--策略模式的应用
策略模式有以上角色: 抽象策略(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角色的方式就很好理解了