我想创建一个线程来每隔几秒发出一些HTTP请求,并且很容易暂时停止并立即恢复。
以下方式是首选,安全和有效吗?
public class Facebook extends Thread {
public boolean running = false;
public void startThread() {
running = true;
}
public void stopThread() {
running = false;
}
public void run() {
while(true) {
while(running) {
//HTTP Calls
Facebook.sleep(2000);
}
}
}
}
答案 0 :(得分:3)
您的代码:
在您的示例中,boolean
应该volatile boolean
才能正常运行。另一个问题是如果running == false
你的线程只是在紧密的循环中烧掉CPU,你可能会想要使用对象监视器或Condition
实际上等待标志成为true
试。
计时器选项:
我建议只为此创建一个Timer
。每个Timer
都隐式获得自己的线程,这就是您要完成的任务。
然后创建一个TimerTask
(下面是FacebookTask
这个)来执行你的任务,并且从你的主控制类中,不需要显式线程,如:
Timer t;
void resumeRequests () {
if (t == null) { // otherwise its already running
t = new Timer();
t.scheduleAtFixedRate(new FacebookTask(), 0, 2000);
}
}
void pauseRequests () {
if (t != null) { // otherwise its not running
t.cancel();
t = null;
}
}
注意,在上面,resumeRequests()
将导致请求在恢复后立即发生(由0 delay参数指定);理论上,如果你在不到2000毫秒的时间内暂停和重复恢复请求率。这对您来说似乎不是一个问题;但另一种实现方法是让计时器持续运行,并在volatile bool
中设置一个FacebookTask
标志,您可以将其设置为启用/禁用它(所以如果它是false
则不会发出请求,但每隔2000毫秒继续检查一次。选择最合适的选择。
其他选项:
您还可以在评论中使用scheduled executor service作为fge提及。它具有比计时器更多的功能,同样易于使用;如果您将来需要添加更多任务,它们也会很好地扩展。
在任何情况下都没有真正的理由直接打扰Thread
s; JDK中有很多很棒的工具可供这项工作使用。
答案 1 :(得分:2)
使用Timer
的建议会更好。但是,如果你想手动进行线程化,那么更像这样的东西会更安全,更好:
class Facebook implements Runnable {
private final Object monitor = new Object();
public boolean running = false;
public void startThread() {
synchronized (monitor) {
running = true;
monitor.notifyAll();
}
}
public void stopThread() {
synchronized (monitor) {
running = false;
}
}
@Override
public void run() {
while(true) {
try {
synchronized (monitor) {
// Wait until somebody calls startThread()
while (!running) {
monitor.wait();
}
}
//HTTP Calls
Thread.sleep(2000);
} catch (InterruptedException ie) {
break;
}
}
}
}
特别注意:
Runnable
而不是子类Thread
,然后使用Runnable
来指定通用Thread
的工作。线程执行的工作与线程本身不同,因此这会产生更好的模型。如果您希望能够通过其他方式执行相同的工作(例如Timer
),它也会更灵活。running
实例变量的状态),您就需要使用某种形式的同步。例如,有一些类AtomicBoolean
内置了这种同步,但有时手动同步也有优势。Object.wait()
和相应的Object.notify()
或Object.notifyAll()
,如演示以上。等待线程消耗零CPU,直到发出信号。由于您无论如何都需要使用wait / notify手动同步,因此使用AtomicBoolean
无法获得额外的优势。已编辑添加:
由于显然有一些关于如何使用它(或原始版本,我猜)的混淆,这是一个例子:
class MyClass {
static void main(String[] args) {
FaceBook fb = new FaceBook();
Thread fbThread = new Thread(fb);
fbThread.start();
/* ... do stuff ... */
// Pause the FaceBook thread:
fb.stopThread();
/* ... do more stuff ... */
// Resume the FaceBook thread:
fb.startThread();
// etc.
// When done:
fbThread.interrupt(); // else the program never exits
}
}
答案 2 :(得分:0)
我建议你使用a guarded blocks并将线程附加到计时器