开发者

Java Thread problem

I want to stop threads by using a boolean field. I have implemented some code to do this which is as follows:

My thread class is like this:

public开发者_如何学编程 class ParserThread implements Runnable {
    private volatile boolean stopped = false;

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

And below is the main thread that starts 10 threads from the function start()

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
    }
}

Now I want to call the stop method of the ParserThread to set "stopped = true" to stop the thread. I want this thing to be done for all the 10 threads.

How can I call that stop method. I want it to be done in the stopAllThreads() method of the Main class.


Take a look at the Executor framework. If you use an ExecutorService you can submit all your work as Runnables. The executor framework will keep track of all these threads, and all the managed threads will receive a shutdown request (interupt) via the shutdownNow() method.

Your threads will have to handle the interrupt properly. See this article for more information.

It's generally easier using the Executor framework to manage sets of threads, collect results, handle exceptions etc.


Here is another alternative approach using an ExecutorService. It requires less code than manipulating Threads directly and offers two alternative methods of stopping the worker threads. It also allows you to potentially capture the results of each work item (if you were to use Callable instances instead of Runnables). Even if you did not wish to capture an explicit return value it allows you to easily marshall any exceptions back onto the main thread.

// 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);
}

Then to shut-down all threads you can either call:

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

... or

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


You have to keep hold of the ParserThread objects themselves:

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();
        }
    }
}

If you need the Thread objects themselves (e.g., to join() with them), either keep track of them separately, or have ParserThread inherit from Thread:

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

Also, as various others have pointed out, stopTheThread() uselessly duplicates the interrupt method on class Thread, so your best bet is:

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();
        }
    }
}

and then in ParserThread, call if (Thread.currentThread().isInterrupted()) as often as you can.


1) There's no need to have some extra volatile variable in order to signal your thread to stop; that's what interrupting is for. In the run() method of the threaded Runnable, you

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) Then, to ask your threaded process to stop, you simply

threads[i].interrupt();

Voilà.


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

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

}

Declare stopped static and when you set it to false all ParserThread runnables will see the visibility.

Just invoke

ParserThread.stopTheThread();

Edit for the fact this will only affect the state of your stopped boolean flag. It will obviously not stop the threads for you :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜