java - 线程怎么可能已经启动了?

标签 java android multithreading thread-safety

我有一个单实例线程类。

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 在实例上调用 startisRunning 为 false,因此调用 start,从而导致崩溃。

一个快速修复方法是不将 isRunning 设置为 false,因为该实例没有任何充分的理由可用于重新启动。然后应将其重命名为 isStarted 以与其功能保持一致。

正确的解决方案是使用 newSingleThreadExecutor,如 @Mani 所建议

关于java - 线程怎么可能已经启动了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23138356/

相关文章:

Java:调用函数如何不处理子函数的异常?

Java - 将引用的库打包到 jar 文件中并重新使用

Linux 上的 Java 到 MySql 连接

Android getExternalFilesDir权限

android - GUI 不显示所有收到的数据包

windows - Windows 线程何时需要消息循环,为什么?

java - 嵌套for循环优化

android - JNI - 从 jstring 到 byte、从 byte 到 string 的传输问题

java - 一个接一个地播放音乐

.net - System.Threading.Monitor.Enter() 如何工作?