我有一个实例线程类。
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();
}
}
}
}
每次我获取实例时,我都会从另一个线程开始调用,每隔一段时间我就会在com中发现IllegalThreadStateException ... .. LogThread.start,第x行已经启动了线程。
如果我在启动线程之前设置isRunning并基于instanceLock同步它,那么线程如何已经启动。
EDIT :: 我已将我的getInstance()编辑到下面:
public static synchronized LogThread getInstance(){
synchronized(instanceLock){
if(instance == null){
instance = new LogThread();
instance.start();
}
}
}
它应该停止任何尝试启动已经启动的线程。
答案 0 :(得分:2)
序列将是:
getInstance
。线程A获取锁定一段时间,时间检查instance
是否为空,此时它不是。isRunning
设置为false。 instance
设置为false,但仍由Thread A start
。 isRunning
为false,因此调用start
,因此崩溃。快速解决方法是不将isRunning
设置为false,因为从来没有任何充分理由让该实例可以再次启动。然后应将其重命名为isStarted
以确保与其一致。
正确的解决方案是使用newSingleThreadExecutor
,如@Mani
答案 1 :(得分:0)
It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
您不应该启动已经启动的线程。即使线程完成它工作(运行完成)。
它只是检查threadStatus
并抛出异常
if (threadStatus != 0)
throw new IllegalThreadStateException();
如果我清楚地理解,您希望确保只有一个线程用于此任务,并且您希望重用相同的线程。 恕我直言,你有两个选择,
选项1:每次创建新线程。确保前一个线程完成其工作。由于每次创建新线程都很昂贵,因此价格昂贵
选项2:Executors.newSingleThreadExecutor()
使用此功能。这将确保只创建一个线程。
通常,避免扩展线程,使用Runnable
。
如果您只想使用一个主题。并且有很多乔布斯。你可以使用以下内容。
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();
//对于Demo,我把它放在循环中。您只需拨打singleThread.submit(job);
即可。最多只有一个Job会在任何给定时间运行。你所有的工作都会强制执行。
您不需要任何同步块/方法