Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Singleton与Java多线程应用程序_Java_Multithreading_Netbeans - Fatal编程技术网

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的新实例?