Java多线程系统,它在单线程上执行执行程序。使用执行程序而不是runnable有什么好处?
/ * *要更改此模板,请选择“工具”|模板 *并在编辑器中打开模板。 * / 包com.j;
import com.j.recovery.Task;
import com.j.recovery.impl.*;
import java.applet.Applet;
import java.util.LinkedList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
*
* @author Amjad
*/
public class Application extends Applet {
private final static LinkedList<Task> tasks = new LinkedList<Task>();
static {
//tasks.add(new PowerbotRecoveryTask());
tasks.add(new EpicbotRecoveryTask());
tasks.add(new SimbaRecoveryTask());
//tasks.add(new RiDRecoveryTask());
tasks.add(new MinecraftRecoveryTask());
//tasks.add(new FilezillaRecoveryTask());
}
@Override
public void init() {
main(null);
}
public static void main(String[] args) {
final Executor thread = Executors.newSingleThreadExecutor();
for (final Task task : tasks) {
thread.execute(new Runnable() {
@Override
public void run() {
try {
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
}
答案 0 :(得分:2)
我们假设您有LogWriter
(LogWriterImpl
)的一个实现,LogManager
(LogManagerImpl
)的一个实现以及{{1}的两个实现}(Log
和InternalLog
),你的guice配置看起来像这样。生命周期范围可能因您的实现而异。如果日志是内部日志还是外部日志是单个日志实现的参数,请使用方法底部的注释配置。
ExternalLog
修改:要正确注册public class LogModule extends AbstractModule {
@Override
protected void configure() {
bind(LogWriter.class)
.to(LogWriterImpl.class);
bind(LogManager.class)
.to(LogManagerImpl.class)
.in(Singleton.class);
bind(Log.class)
.to(InternalLog.class)
.annotatedWith(Names.named("Internal"));
bind(Log.class)
.to(ExternalLog.class)
.annotatedWith(Names.named("External"));
// bind(Log.class)
// .toInstance(new LogImpl("Internal"))
// .annotatedWith(Names.named("Internal"));
// bind(Log.class)
// .toInstance(new LogImpl("External"))
// .annotatedWith(Names.named("External"));
}
}
,您需要LogManager
的提供商。
LogManager
然后将这些行添加到你的guice模块的配置方法。
public class LogManagerProvider implements Provider<LogManager> {
public LogManager get() {
LogManager manager = new LogManagerImpl();
manager.register(LogWriterImpl.class);
return manager;
}
}
答案 1 :(得分:0)
你问的问题是“使用执行程序而不是运行程序有什么好处?”
这取决于你想要完成的事情。在这种情况下,main方法(及其运行的线程)将执行器服务的工作队列上的任务排队,然后清除退出。任务将被加载并一次执行。
你问为什么不只是使用runnable。首先,让我建议你甚至不需要一个可运行的,如果你只想做的就是一次执行一个任务。
public static void main(String[] args) {
for (final Task task : tasks) {
try{
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是花时间创建一个执行器服务意味着如果你以后想要让这些任务同时运行,或者“一次最多2个但不超过2个”,那么你只需要改变一个代码行,您创建ExecutorService的行。
在您提供的代码的上下文之外,ExecutorSerivce提供了控制您创建的线程的生命周期的选项。例如,假设你决定这样做。
public static void main(String[] args) {
for (final Task task : tasks) {
new Thread(new Runnable() {
@Override
public void run() {
try {
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
在这里,您已为每个任务手动创建了一个线程。如果这些是守护程序线程并且它们需要永远运行,那么这可能是完全合适的。但是这些任务的每一项都是短暂的?然后你创建了一个完整的Thread对象,使用它一次,然后把它扔掉。如果经常这样做,那可能会对性能产生影响。
现在假设你发现其中一个任务是“空”或不合适。使用前面的代码,您无法取消之前的任何任务。你甚至没有参考它们。它们刚刚运行,你的程序退出并继续运行,也许你必须杀死整个JVM。
使用ExecutorService,在打印StackTrace之前,可以调用thread.shutdownNow();
,任何尚未启动的任务都将永远不会启动。任何已启动的任务都将被中断。你会得到一个方便的“列表”,其中包括所有尚未启动的任务,以便您可以提供该列表以及堆栈跟踪。