Java 如何使用ScheduledExecutors只运行一次后台线程?
下面是我的界面-Java 如何使用ScheduledExecutors只运行一次后台线程?,java,multithreading,background-thread,scheduledexecutorservice,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 interface IClient { public String
public interface IClient {
public String read(ClientInput input);
}
public class TempClient implements IClient {
@Override
public String read(ClientInput input) {
}
}
这是我的接口实现-
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
}
公共类临时调度器{
private final ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
公共无效startScheduler(){
final ScheduledFuture taskHandle=scheduler.scheduleAtFixedRate(new Runnable()){
公开募捐{
试一试{
callServers();
}捕获(例外情况除外){
例如printStackTrace();
}
}
},0,10L,时间单位为分钟);
}
}
//... 一些代码
}
问题陈述:-
TempClientFactory
,它工作得非常好如果我的理解是正确的,假设我只调用一次TempClientFactory,那么它将启动后台线程,并且我的后台线程将每10分钟继续运行一次。。如果我再次给我的工厂打电话,那么它会再次启动同样的后台,也会每10分钟运行一次?或者它将只启动一个后台线程,每10分钟运行一次?使用一个singleton方法,该方法将确保您拥有一个类的单个实例。要创建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
}
公共类TempClientFactory{
公共静态IClient getInstance()
{
TempScheduler obj=TempScheduler.getTempScheduler();
如果(对象标志==假)
{
obj.startScheduler();
}
返回ClientHolder.INSTANCE;
}
私有静态类ClientHolder{
私有静态最终TempClient实例=新TempClient();
}
}
公共类临时调度器{
private final ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
publicstatictempscheduler=null;
公共布尔旗;
公共无效startScheduler(){
flag=true;
final ScheduledFuture taskHandle=scheduler.scheduleAtFixedRate(new Runnable()){
公开募捐{
试一试{
callServers();
}捕获(例外情况除外){
例如printStackTrace();
}
}
},0,10L,时间单位为分钟);
}
}
专用临时调度器()
{
}
同步的公共静态TempScheduler getTempScheduler()
{
if(调度程序==null)
{
调度器=新的临时调度器();
}
返回调度程序;
}
//... 一些代码
}
您需要手动防止再次调用它。您可以向内部类添加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为实例化singleton而保证的线程安全、延迟加载类似,它还将保证在此处启动调度程序的一次性访问
因此,您将只启动并计划线程运行一次
另外,我建议您转换
ex.printStackTrace()代码>转换为实际的日志语句。直接使用,而不是给它一个重复周期。如果您再次调用schedule
,或者当前调用它的同级调用,那么它将创建第二个线程。我只需要一个后台线程,它应该每10分钟运行一次。。我不想让客户继续打电话给我们,然后我的后台线程被调用。。。我还有别的办法吗?谢谢你的帮助ex.printStackTrace
仅用于演示。。我的伐木工人在那边。。因此,如果我按照您建议的方式执行,它只会启动我的后台线程一次,如果有人再次致电我的工厂,那么它将不会再次启动后台线程。。正当而且,它也是线程安全的吗?正确。它是线程安全的,原因与singleton的实例化相同——JVM保证它使用内部类“static
内容,而不锁定。它只会发生一次,你可以阅读更多关于它的内容。它与单例实例化有关,但是这个想法适用于我在这里所做的事情。