我有两个连续运行的线程实例。我怎么能停止线程的第一个实例。请找到以下代码: -
public class Thread1 extends Thread {
static volatile boolean bThreadStop = false ;
public void run() {
while(!bThreadStop) {
System.out.println("THREAD1");
//BUSINESS LOGIC//
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
t1.start();
Thread1 t2 = new Thread1();
t2.start();
}
}
根据上面的例子,我需要停止Thread1的t1实例。请建议我如何实现同样的目标。
答案 0 :(得分:1)
你的问题的直接答案是你的标志是静态的,所以你的Thread子类的所有实例都看到相同的标志;使其成为实例范围而不是静态意味着可以单独停止各个线程对象。同时使标志为volatile将意味着对Thread子类实例可以看到对标志的更新。如果没有volatile
,JVM可以优化标记检查。
但是使用你自己的旗帜取消线程并不是一个好主意。这里有一个非常好的标志,已经为你制作并融入了Thread类。事实上,它比你想出的任何东西都要好,因为你的线程无法停止睡眠或等待检查你自己的旗帜,所以一旦你设置它,线程可能需要一段时间才能响应。但是如果你使用中断设施,那么线程可以检查自己的中断标志并立即停止睡眠或等待。
这是您重复使用中断的示例。在您的示例中,输出不区分Thread1和Thread2,我添加了一个名称来帮助它。此外,我为线程添加了一个睡眠(为了减少写入控制台的内容量以及演示中断睡眠线程),并且在等待足够长的时间后,示例也取消了第二个线程。明确哪个主题被取消了。
public class Thread1 extends Thread {
public Thread1(String name) {
super(name);
}
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println(getName());
//BUSINESS LOGIC//
Thread.sleep(1000L);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("thread " + getName() + " woke up");
}
System.out.println("thread " + getName() + " finished");
}
public static void main(String[] args) throws Exception {
Thread1 t1 = new Thread1("t1");
t1.start();
Thread1 t2 = new Thread1("t2");
t2.start();
Thread.sleep(5000L);
t1.interrupt(); // cancel the first thread
Thread.sleep(5000L);
t2.interrupt(); // cancel the second thread
}
}
输出如下:
t1
t2
t1
t2
t2
t1
t2
t1
t2
t1
thread t1 woke up
thread t1 finished
t2
t2
t2
t2
t2
thread t2 woke up
thread t2 finished
我还有另一个线程中断示例,其中包含更多详细信息here。
答案 1 :(得分:0)
如何将bThreadStop标记为实例变量而不是使其变为静态?
答案 2 :(得分:0)
您的bThreadStop
变量会停止所有正在运行的线程。如果你把它变成一个实例变量(甚至更好,添加一个setter方法),你就可以说t2.stop()
并且只停止t2
。
查看我对How to find and stop all currently running threads?的回答,以及有关如何正确停止线程的其他讨论。
通过该讨论,StoppableRunnable
以干净,线程安全的方式提供您正在寻找的行为:
public abstract class StoppableRunnable implements Runnable {
private volatile boolean stopWork;
private boolean done;
public final void run() {
setup();
while(!stopWork && !done) {
doUnitOfWork();
}
cleanup();
}
/**
* Safely instructs this thread to stop working,
* letting it finish it's current unit of work,
* then doing any necessary cleanup and terminating
* the thread. Notice that this does not guarentee
* the thread will stop, as doUnitOfWork() could
* block if not properly implemented.
*/
public void stop() {
stopWork = true;
}
protected void done() {
done = true;
}
protected void setup() { }
protected void cleanup() { }
/**
* Does as small a unit of work as can be defined
* for this thread. Once there is no more work to
* be done, done() should be called.
*/
protected abstract void doUnitOfWork();
}
答案 3 :(得分:0)
正如您所看到的,有很多答案。我粘贴了我的贡献:
public class Thread1 extends Thread {
private volatile boolean threadRunning = true;
private final int id;
public Thread1 (int id){
this.id = id;
}
public void run() {
while(threadRunning) {
System.out.println("THREAD" + id);
}
}
public void stopTheThread(){
threadRunning = false;
}
public static void main(String[] args) {
Thread1 t1 = new Thread1(1);
Thread1 t2 = new Thread1(2);
t1.start();
t2.start();
t2.stopTheThread();
t1.stopTheThread();
}
}
我也喜欢基于捕获InterruptedException的Nathan Hughes实现。