如何使用ScheduledExecutors只运行一次后台线程?

时间:2014-01-22 04:46:08

标签: java multithreading background-thread scheduledexecutorservice

以下是我的界面 -

public interface IClient {
    public String read(ClientInput input);
}

这是我对界面的实现 -

public class TempClient implements IClient {

    @Override
    public String read(ClientInput input) {

    }
}

以下是我的工厂代码 -

public class TempClientFactory {

    public static IClient getInstance() {
    new TempScheduler().startScheduler();
    return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();
    }
}

现在我有一个工厂可以获得这样的TempClient实例,所以客户将在调用我们的代码时使用我们的工厂,如下所示。

IClient client = TempClientFactory.getInstance();
client.read(input);

以下是我的后台线程代码 -

public class TempScheduler {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        public void startScheduler() {
            final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(new Runnable() {
                public void run() {
                try {
                    callServers();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                }
            }, 0, 10L, TimeUnit.MINUTES);
        }
    }

    //... some code
}

问题陈述: -

  1. 现在我有一个后台线程,它将在后面运行 从URL获取数据,解析并存储它的场景 在变量中。现在我想要的是我们的客户一开始 通过使用工厂打电话来使用我们的代码,我想要 开始的后台线程。所以我决定接听电话 我上面的TempClientFactory并且工作得非常好......
  2. 现在问题的方法是,客户将继续调用我的TempClientFactory,以便它始终保持启动后台线程..我正在寻找的是,如果后台线程启动一次,那么我不想要从另一个线程再次启动它但它应该继续在场景后面每10分钟运行一次,因为它已经是第一次启动了。

    如果我的理解是正确的,假设我一次调用我的TempClientFactory,那么它将启动后台线程,我的后台线程将每隔10分钟继续运行..如果我再次调用我的工厂,那么它将会再次启动相同的背景,也会每10分钟运行一次?或者它将只启动一个后台线程,每10分钟运行一次?

2 个答案:

答案 0 :(得分:0)

使用单例方法,它将确保您只有一个类的实例。创建TempScheduler的对象只需调用

 public class TempClientFactory {

    public static IClient getInstance() 
   {

       TempScheduler  obj=TempScheduler.getTempScheduler(); 
       if(obj.flag==false) 
       {
        obj.startScheduler();
       }
       return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();
    }
}






 public class TempScheduler {

            private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            public static TempScheduler scheduler=null;
            public bool flag;

                public void startScheduler() {
                    flag=true;
                    final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(new Runnable() {
                        public void run() {
                        try {
                            callServers();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                        }
                    }, 0, 10L, TimeUnit.MINUTES);
                }
            }

            private TempScheduler()
            {

            }

            synchronized public static TempScheduler getTempScheduler()
            {
             if(scheduler==null)
             {
                scheduler=new TempScheduler();
             }
             return scheduler;
           }


            //... some code
        }

答案 1 :(得分:0)

您需要手动阻止再次调用它。您可以向内部类添加static块。

public class TempClientFactory {
    public static IClient getInstance() {
        return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();

        static {
            // You could do this here, as well, if it were more complicated
            //  than a one-line statement (e.g., requires try/catch):
            //INSTANCE = new TempClient();

            new TempScheduler().startScheduler();
        }
    }
}

与线程安全,JVM保证实例化单例的延迟加载类似,它也保证一次性访问启动调度程序。

因此,您只会启动并安排一次运行您的线程。

另外,我建议您将ex.printStackTrace();转换为实际的日志声明。

相关问题