简体   繁体   English

如何才能启动线程?

[英]How can thread already be started?

I have a single instance thread class. 我有一个单实例线程类。

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();
            }
        }
    }
}

I am calling start from another thread each time i get the instance, and every once in a while i get a IllegalThreadStateException in com.......LogThread.start, line x Thread already started. 每当我获取实例时,我都会从另一个线程开始调用,每隔一段时间,我会在com ....... LogThread.start中看到一个IllegalThreadStateException异常,第x行线程已启动。

How can the thread already be started if I set isRunning before starting the thread AND synchronize it based on instanceLock. 如果我在启动线程并基于instanceLock对其进行同步之前设置了isRunning,那么如何启动该线程。

EDIT:: I have edited my getInstance() to below: 编辑::我已经将我的getInstance()编辑为以下内容:

 public static synchronized LogThread getInstance(){
     synchronized(instanceLock){
         if(instance == null){
             instance = new LogThread();
             instance.start();
         }
     }
 }

it should stop any attempts to start a thread that is already started. 它应该停止任何尝试启动已经启动的线程的尝试。

The sequence would be this: 顺序如下:

  • Thread A calls getInstance . 线程A调用getInstance Thread A takes the lock for a while, time to check that instance is not null, which it isn't at this point. 线程A锁定了一段时间,需要时间来检查instance是否不为null(此时不是)。
  • Thread LogThread completes it's execution, isRunning is set to false. 线程LogThread完成其执行, isRunning设置为false。 instance is set to false, but is still retained by Thread A instance设置为false,但仍由线程A保留
  • Thread A calls start on the instance. 线程A调用start实例start isRunning is false, therefore start is called, hence the crash. isRunning为false,因此将调用start ,从而导致崩溃。

A quick fix would be to not set isRunning to false, since there is never any good reason for that instance to be available for starting again. 一个快速的解决方法是不将isRunning设置为false,因为从没有任何充分的理由使该实例可再次启动。 It should then be renamed isStarted for consistency with what it does. 然后应将其重命名为isStarted ,以isStarted功能一致。

A proper solution would be to use a newSingleThreadExecutor , as suggested by @Mani 正确的解决方案是使用newSingleThreadExecutor建议的newSingleThreadExecutor

It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.

From Thread.start Thread.start

You should not start the thread , which is already started. 您不应该启动已经启动的线程。 even though the thread completes it work ( run completed). 即使线程完成了它的工作(运行完成)。

It simply checks the threadStatus and throw exception 它只是检查threadStatus并抛出异常

  if (threadStatus != 0)
            throw new IllegalThreadStateException();

If i understands clearly, you want to make sure only one thread spend for this task, and you want to reuse the same thread. 如果我清楚理解,您想确保只有一个线程花费在此任务上,并且您想重用同一线程。 IMHO , you have two choices, 恕我直言,您有两种选择,

Option 1: Create new thread each time. 选项1:每次创建新线程。 make sure the previous thread is completed its work. 确保先前的线程已完成其工作。 It is expensive since creating new thread each time is expensive 这很昂贵,因为每次创建新线程都很昂贵

Option 2: Executors.newSingleThreadExecutor() use this. 选项2: Executors.newSingleThreadExecutor()使用此选项。 this will make sure only one thread is created. 这将确保仅创建一个线程。

And in general , Avoid extend thread, use Runnable . 通常,避免扩展线程,请使用Runnable

If you want to use only one thread. 如果只想使用一个线程。 and have lot of Jobs. 并且有很多工作。 you could use the following. 您可以使用以下内容。

class LogJob implements Runnable{
    @Override
    public void run() {
        // Do your Job
    }
}

  ExecutorService singleThread = Executors.newSingleThreadExecutor();
LogJob job = new LogJob();
for (int i=0;i<100;i++){
    singleThread.submit(job);
}
singleThread.shutdown();

// For Demo i have put it in loop. //对于演示,我将其置于循环中。 You can just call singleThread.submit(job); 您可以只调用singleThread.submit(job); . At max only one Job would run at any given time. 在任何给定时间最多只能运行一个Job。 and all your jobs would compelte. 这样您的所有工作都会变得很迫切。

You don't need any Sync block / method 您不需要任何同步块/方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SurfaceView和线程已启动异常 - SurfaceView and thread already started exception 如何中止已经启动的swing worker线程? - How to abort a already-started swing worker thread? IllegalThreadStateException:线程已在新线程上启动 - IllegalThreadStateException: Thread already started on a new Thread Java线程错误IllegalThreadState线程已经启动 - Java Threading Error IllegalThreadState thread already started 恢复活动时“线程已经开始” - “Thread already started” when resuming the activity java.lang.IllegalThreadStateException:线程已启动 - java.lang.IllegalThreadStateException: Thread already started 如何验证线程中的命令是否已在Java中成功启动并且可以启动另一个线程? - How to verify if command in the thread is successfully started in Java and another thread can be started? 如何在Android中的onCreate()中启动多个线程而不使用for循环启动线程(IllegalThreadStateException)? - How Do I start multiple threads in Android in onCreate() without getting Thread Already started (IllegalThreadStateException) using for loop? java.lang.IllegalThreadStateException:线程已经启动,而只有 1 个线程 - java.lang.IllegalThreadStateException: Thread already started while there is only 1 thread 如何确定我的android runnable在辅助线程上启动? - How can I be sure that my android runnable started on a worker thread?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM