[英]Java - Ideal use of wait and notify?
到目前为止,该代码在测试中似乎可以正常工作。 但是,我是多线程技术的新手,并且想知道这段代码是否理想,因为我知道关于并发性有很多“缺点”。
有没有更好的方法在单个线程上为排队的Runnables执行程序? 这是我第一次制作,所以我倾向于相信有更好的东西。
public class ExplosionExecutor{
private static List<Runnable> queue= new ArrayList<Runnable>();
private static Thread thread= new Thread(new Runnable() {
public void run() {
while(true){
Runnable[] queuedump;
synchronized (queue) {
if(queue.size()==0){
try {
queue.wait();
} catch (InterruptedException e){e.printStackTrace();}
}
queuedump= queue.toArray(new Runnable[0]);
queue.clear();
}
for(Runnable r : queuedump)
r.run();
}
}
}, "Nuke Explosions");
static{
thread.start();
}
public static void execute(Runnable command) {
synchronized (queue) {
queue.add(command);
queue.notify();
}
}
}
没关系-ish。
最好不要重新发明轮子。
1)有些阻塞队列具有等待新项目的方法,并且已经同步:
public static void main(String[] args) throws Exception {
final BlockingQueue<Runnable> r = new LinkedBlockingQueue<>();
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
r.take().run();
} catch (InterruptedException ex) {
return;
}
}
}
});
r.add(new Runnable() {
@Override
public void run() {
//do stuff
}
});
}
2)有一个ExecutorService
API封装了所有这些行为:
public static void main(String[] args) throws Exception {
final ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(new Runnable() {
@Override
public void run() {
//do stuff
}
});
}
3)如果您要检查已提交任务的成功和/或等待完成任务的摘要,则无法使用API来完成。 使用ExecutorService
您可以非常轻松地完成此操作。
public static void main(String[] args) throws InterruptedException {
final ExecutorService es = Executors.newSingleThreadExecutor();
final Future<?> f = es.submit(new Runnable() {
@Override
public void run() {
//do stuff
}
});
try {
//wait
f.get();
} catch (ExecutionException ex) {
//there was an exeception in the task
}
}
最后一点是,您实现代码的方式无法停止使用者线程。
在我的第一个示例中,您将需要手动调用t.interrupt()
,由于我的实现,这将使线程退出。 在第二个/第三个示例中,您将需要调用ExecutorService.shutdown()
来停止使用者线程。
如果不停止线程,则除非它们是守护程序,否则程序将不会退出。
您为什么要自己实施? Java具有内置的ExecutorService,可以在单个线程上运行Runnables http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
//runs all Runnables in a single thread, one at a time
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(runnable);
这里有一些改进...当然,如果您使用BlockingQueue / ExecutorService,我们无需担心同步/并发性。
另外,您还可以使用并发锁API(ReentrantLock或Condition类),而不是同步/等待/通知。
theexamtime.com
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.