[英]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: 顺序如下:
getInstance
. getInstance
。 Thread A takes the lock for a while, time to check that instance
is not null, which it isn't at this point. instance
是否不为null(此时不是)。 isRunning
is set to false. isRunning
设置为false。 instance
is set to false, but is still retained by Thread A instance
设置为false,但仍由线程A保留 start
on the instance. 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.