Singleton与Java多线程应用程序
简单地说,我想单击一个按钮来运行后台任务(分离线程)。我面临两个问题:Singleton与Java多线程应用程序,java,multithreading,netbeans,Java,Multithreading,Netbeans,简单地说,我想单击一个按钮来运行后台任务(分离线程)。我面临两个问题: 如果用户在该按钮上多次单击==>将显示多个线程,该怎么办 创造 即使我使用Singleton机制,我也会面临另一个问题,即即使任务完成后,用户不能再重新运行流程(再次单击按钮),也只会创建一次该实例 我的班级: package mypack.check; public class RunnableCheck implements Runnable { private Thread t; private
- 如果用户在该按钮上多次单击==>将显示多个线程,该怎么办 创造
- 即使我使用Singleton机制,我也会面临另一个问题,即即使任务完成后,用户不能再重新运行流程(再次单击按钮),也只会创建一次该实例
package mypack.check;
public class RunnableCheck implements Runnable {
private Thread t;
private static RunnableCheckFeeders instance;
public RunnableCheckFeeders getDefault() {
if (instance == null) {
instance = new RunnableCheckFeeders();
}
return instance;
}
@Override
public void run() {
//What the thread is supposed to do...
}
public void start() {
if (t == null) {
t = new Thread(this, "My task");
t.start();
}
}
}
RunnableCheckFeeders.getDefault().start();
调用方类中的:
package mypack.check;
public class RunnableCheck implements Runnable {
private Thread t;
private static RunnableCheckFeeders instance;
public RunnableCheckFeeders getDefault() {
if (instance == null) {
instance = new RunnableCheckFeeders();
}
return instance;
}
@Override
public void run() {
//What the thread is supposed to do...
}
public void start() {
if (t == null) {
t = new Thread(this, "My task");
t.start();
}
}
}
RunnableCheckFeeders.getDefault().start();
我尝试了同步方法,但没有成功,任何提议都是受欢迎的。当用户多次单击时,您希望事件发生多次,还是只发生一次?如果多次执行,您不需要单例,而是创建一个工作队列 您可以通过以下两种方式之一来实现这一点,第一种是使用一个想要一个线程池,很可能使用来自的线程池 第二个选项是让一个队列从中读取,并让一个线程从队列中读取
如果希望事件只发生一次,则需要禁用该按钮,直到它完成,使start同步,以便一次只能有一个线程调用它,然后在线程完成后将
t
设置为null
(即run()
中的最后一项).您的start
方法不能保证只创建一个“我的任务”线程,即使只有一个RunnableCheck
实例:因为对线程引用和后续分配的检查不是原子的,如果两个线程同时将t==null
计算为true(或者,至少第二个线程可以在第一个线程能够将非null值分配给t
之前将其计算为true),则可以创建并启动两个线程
您可以通过以下方式对此进行防范:
- 使
方法同步,因此多个线程不能同时运行该方法李>start
- 添加一个
来记录线程是否已创建/启动。通过原子地更新此标志的值,两个线程无法将其设置为AtomicBoolean
,因此无法创建和启动两个新的true
:线程
private final AtomicBoolean started = new AtomicBoolean(); private Thread t; public void start() { if (!started.compareAndSet(false, true)) { return; } t = new Thread(this, "My task"); t.start(); }
- 我建议您使用Executor服务
enum RunOne {; // no instances
static final ExecutorService service = Executors.newSingleThreadedExecutor();
static Future last = null;
static synchronized void run(Runnable run) {
if (last != null && !last.isDone()) return;
last = service.submit(run);
}
}
只有在尚未运行任务时,才会提交新任务。它不会创建多个线程,但您可以在前一个线程完成后提交任务。您可以调用
service.shutdown()
停止服务。在线程加载完成之前,您不能禁用该按钮吗?Java的未来
在这种情况下很有用:。如果线程完成,您可以检查Future
。因为getDefault
不是静态的,所以您需要创建RunnableCheck
的实例来调用getDefault
来获取静态实例。因此,RunnableCheckFeeders.getDefault()
甚至不编译。单击按钮时,是否正在创建RunnableCheck的新实例?