可停止的Runnable实现与多线程相关技术问询
可停止Runnable的线程安全相关问题解答
问题背景
我实现了MyRunnableWhichIsStoppable类作为可停止的Runnable,通过boolean类型的running变量控制线程运行,同时提供了synchronized修饰的isRunning()和stopRunning()方法。针对这个实现,有三个疑问需要解答:
1. 若为两个线程分别创建独立的MyRunnableWhichIsStoppable实例,方法中的synchronized关键字是否必要?
完全没必要。因为每个线程持有独立的实例,running变量是每个实例的私有成员,不存在多线程共享同一变量的场景,自然不会有线程安全冲突。synchronized在这里只会带来额外的锁开销,直接去掉即可。
2. MyRunnableWhichIsStoppable类是否线程安全?running变量是否需要修改?
这个问题要分两种场景看:
- 场景一:每个线程使用独立的实例
这种情况下不存在共享变量,不管有没有synchronized或者volatile,类都是线程安全的。此时synchronized完全是多余的,可以移除。 - 场景二:单个实例被多个线程共享
当前实现存在线程安全问题:running变量没有volatile修饰,会有可见性问题——当一个线程修改了running的值,其他线程可能无法立即看到最新值,导致线程无法及时响应停止指令。- 虽然
synchronized方法能保证可见性,但它的开销比volatile大很多。而running是boolean类型,赋值操作本身是原子性的,所以只需要给running加上volatile修饰,就能保证多线程下的可见性,比用synchronized更高效。
总结:如果类可能被多线程共享实例,必须把running修改为volatile boolean running;如果确定是每个线程一个实例,当前实现没问题,但建议去掉synchronized以减少开销。
3. 能否通过继承Thread的MyThread类持有MyRunnableWhichIsStoppable,调用stopRunning()停止线程?
当然可以,这是一种很常规的实现方式。示例代码如下:
class MyThread extends Thread { private final MyRunnableWhichIsStoppable stoppableRunnable; public MyThread(MyRunnableWhichIsStoppable runnable) { super(runnable); this.stoppableRunnable = runnable; } public void stopThread() { stoppableRunnable.stopRunning(); } }
使用时,只需要创建MyThread实例并启动,之后调用stopThread()方法就能触发Runnable中的停止逻辑。注意要确保MyRunnableWhichIsStoppable的run()方法里会循环检查isRunning()的状态,比如:
public class MyRunnableWhichIsStoppable implements Runnable { private volatile boolean running = true; @Override public void run() { while (isRunning()) { // 执行线程任务 } } public boolean isRunning() { return running; } public void stopRunning() { running = false; } }
内容的提问来源于stack exchange,提问作者Arunabha Ghosh
相关产品推荐
相关产品推荐

