Java线程问题

时间:2009-10-23 13:27:38

标签: java multithreading

我想通过使用布尔字段来停止线程。我已经实现了一些代码来执行此操作,如下所示:

我的线程类是这样的:

public class ParserThread implements Runnable {
    private volatile boolean stopped = false;

    public void stopTheThread() {
        stopped = true;
    }
    :
    :
}

以下是从函数start()

启动10个线程的主线程
public class Main() {
    Thread [] threads;

    public void start() {
        for(int i = 0; i < 10; i++) {
            threads[i] = new Thread(new ParserThread());
        }       
    }

    public void stop() {
        // code to stop all the threads
    }
}

现在我想调用ParserThread的stop方法来设置“stopped = true”来停止线程。我想要为所有10个线程完成这件事。

如何调用stop方法。我希望它可以在Main类的stopAllThreads()方法中完成。

5 个答案:

答案 0 :(得分:11)

看看Executor框架。如果您使用ExecutorService,则可以将所有工作提交为Runnables。执行程序框架将跟踪所有这些线程,所有托管线程将通过shutdownNow()方法接收关闭请求(中断)。

您的线程必须正确处理中断。有关详细信息,请参阅this article

使用Executor框架管理线程集,收集结果,处理异常等通常更容易。

答案 1 :(得分:6)

以下是使用ExecutorService的另一种替代方法。它比直接操作Threads需要更少的代码,并提供了两种停止工作线程的替代方法。它还允许您潜在地捕获每个工作项的结果(如果您使用Callable实例而不是Runnables)。即使您不希望捕获显式返回值,它也允许您轻松地将任何异常编组回主线程。

// Array of Runnables that we wish to process.
ParserThread[] parserThreads = ...

// Create executor service containing as many threads as there are Runnables.
// (Could potentially have less threads and let some work items be processed
// sequentially.)
ExecutorService execService = Executors.newFixedThreadPool(parserThreads.length);

// Submit each work item.  Could potentially store a reference to the result here
// to capture exceptions.
for (ParserThread runnable : parserThreads) {
  execService.submit(runnable);
}

然后关闭所有可以调用的线程:

executorService.shutDown(); // Initiates an orderly shut-down of the service.

......或

executorService.shutDownNow(); // Stops all tasks, interrupting waiting tasks.

答案 2 :(得分:5)

您必须自己保留ParserThread对象:

public class Main() {
    ParserThread[] parserthreads = new ParserThread[10];

    public void start() {
        for(int i = 0; i < 10; i++) {
            parserthreads[i] = new ParserThread();
            new Thread(parserthreads[i]).start();
        }       
    }

    public void stop() {
        for (int i = 0; i < 10; i++) {
            parserthreads[i].stopTheThread();
        }
    }
}

如果您需要Thread对象本身(例如,与join()一起使用它们),要么单独跟踪它们,要么让ParserThread继承自Thread:

public class ParserThread extends Thread {
    private volatile boolean stopped = false;
    public void stopTheThread() {
        stopped = true;
    }
}

另外,正如其他人指出的那样,stopTheThread()无用地复制了interrupt课上的Thread方法,所以最好的选择是:

public class Main() {
    Thread[] parserthreads = new Thread[10];

    public void start() {
        for(int i = 0; i < 10; i++) {
            parserthreads[i] = new Thread(new ParserThread());
            parserthreads[i].start();
        }       
    }

    public void stop() {
        for (int i = 0; i < 10; i++) {
            parserthreads[i].interrupt();
        }
    }
}

然后在ParserThread中,尽可能多地拨打if (Thread.currentThread().isInterrupted())

答案 3 :(得分:2)

1)没有必要使用一些额外的volatile变量来表示你的线程停止;这就是中断的目的。在线程Runnable的run()方法中,你

while (!Thread.currentThread().isInterrupted()) {
    // do whatever your thing is
    // some things, like sleeping, can throw InterruptedException when
    // interrupted, so
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        break;
    }
}
// clean up here

2)然后,要求您的线程进程停止,您只需

threads[i].interrupt();

瞧。

答案 4 :(得分:2)

public class ParserThread implements Runnable {
private static volatile boolean stopped = false;

public static void stopTheThread() {
    stopped = true;
}

}

声明已停止静态,当您将其设置为false时,所有ParserThread runnable都将看到可见性。

只需调用

ParserThread.stopTheThread();

编辑事实,这只会影响已停止的布尔标志的状态。它显然不会为你阻止线程:)