我有一个单实例线程类。
public class LogThread extends Thread{
private static LogThread instance = null;
private volatile boolean isRunning = false;
private final static Object instanceLock = new Object();
public static synchronized LogThread getInstance(){
synchronized(instanceLock){
if(instance == null)
instance = new LogThread();
}
return instance;
}
@Override
public run(){
//Doing some run stuff
//Once run is finished
synchronized(instanceLock){
isRunning = false;
instance = null;
}
}
@Override
public synchronized void start() {
synchronized (instanceLock){
if(!isRunning){
isRunning = true;
super.start();
}
}
}
}
每次获取实例时,我都会从另一个线程调用 start,并且每隔一段时间我就会在 com.......LogThread.start,第 x 行线程已启动中收到 IllegalThreadStateException。
如果我在启动线程之前设置了isRunning并基于instanceLock同步它,线程怎么可能已经启动了。
编辑:: 我已将 getInstance() 编辑为以下内容:
public static synchronized LogThread getInstance(){
synchronized(instanceLock){
if(instance == null){
instance = new LogThread();
instance.start();
}
}
}
它应该停止任何启动已启动线程的尝试。
最佳答案
顺序是这样的:
- 线程 A 调用
getInstance
。线程 A 获取锁一段时间,是时候检查instance
是否不为 null,而此时它不为 null。 - Thread LogThread 完成执行,
isRunning
设置为 false。instance
设置为 false,但仍被线程 A 保留 - 线程 A 在实例上调用
start
。isRunning
为 false,因此调用start
,从而导致崩溃。
一个快速修复方法是不将 isRunning
设置为 false,因为该实例没有任何充分的理由可用于重新启动。然后应将其重命名为 isStarted
以与其功能保持一致。
正确的解决方案是使用 newSingleThreadExecutor
,如 @Mani 所建议
关于java - 线程怎么可能已经启动了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23138356/