问题
In the following java application, I use TwitterStream to gather tweets using sample function. I need to start and stop the stream whenever user wants, but I get the following exception:
java.util.concurrent.RejectedExecutionException: Task twitter4j.StatusStreamBase$1@74e75335 rejected from java.util.concurrent.ThreadPoolExecutor@5117b235[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 2]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
at twitter4j.DispatcherImpl.invokeLater(DispatcherImpl.java:58)
at twitter4j.StatusStreamBase.handleNextElement(StatusStreamBase.java:80)
at twitter4j.StatusStreamImpl.next(StatusStreamImpl.java:56)
at twitter4j.TwitterStreamImpl$TwitterStreamConsumer.run(TwitterStreamImpl.java:568)
When the user presses "Crawl" or "Stop Crawling", the method actionPerformed is correctly called. However, if the user presses Crawl and then presses Stop and then again presses Crawl, I get the error above
I have several classes, but the principal ones are the followings:
The first one creates the interface and comunicates with the crawler class.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class StackOv extends JFrame implements ActionListener{
private JTextArea usersSaved;
private boolean alreadyCrawling;
private boolean stopReceived;
private Stream stream;
private JButton Crawl;
private JButton stopCrawl;
private Mongo m;
public StackOv(){
this.stopReceived = false;
this.alreadyCrawling = false;
setLayout(new FlowLayout(FlowLayout.CENTER));
Crawl = new JButton("Crawl");
Crawl.setActionCommand("Crawl");
Crawl.addActionListener(this);
stopCrawl = new JButton("Stop Crawling");
stopCrawl.setActionCommand("Stop Crawling");
stopCrawl.addActionListener(this);
m = new Mongo(); //instance of class that uses MongoDB
/*
*
*bla bla bla create the rest of the interface as you wish
*add(button)
*add(button)
*etc...
*/
}
public void setOut(String out){
usersSaved.setText(out);
}
public void setOffAlreadyCrawling(){
this.alreadyCrawling = false;
}
@Override
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("Stop Crawling") && !this.stopReceived){
this.stopReceived = true;
stream.setStop();
}
else if(e.getActionCommand().equals("Crawl") && !alreadyCrawling){
if(stream != null && stream.isAlive()){
stream.interrupt();
}
alreadyCrawling = true;
stream = new Stream(m, this);
//independently of using one of the following two calls, I get the same exception above
stream.execute1();
//stream.start();
this.stopReceived = false;
}
}
public void main(String[] args){
StackOv so = new StackOv();
so.setSize(800, 800);
so.setVisible(true);
}
}
The following class is the crawler class, that shutdown twitterStream when stopCrawl is true or when twitterStream has sampled a number of tweets over the maximum limit.
import java.awt.TextArea;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import twitter4j.FilterQuery;
import twitter4j.StallWarning;
import twitter4j.Status;
import twitter4j.StatusDeletionNotice;
import twitter4j.StatusListener;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.TwitterStream;
import twitter4j.TwitterStreamFactory;
public class Stream extends Thread{
private Crawler cr;
private TwitterStream twitterStream;
private int maxTweets;
private int usersSaved;
private Mongo database;
private CreateIndex ci;
private TwitterSearch twitterSearch;
private static boolean stopCrawl;
public Stream(Mongo database, TwitterSearch twitterSearch){
Stream.stopCrawl = false;
this.database = database;
this.cr = new Crawler(database);
this.twitterStream = new TwitterStreamFactory(DefaultConfiguration.getConfiguration()).getInstance();
this.maxTweets = 1000;
ci = new CreateIndex(database);
this.twitterSearch = twitterSearch;
}
public void setStop(){
Stream.stopCrawl = true;
}
public void execute() throws TwitterException {
final List<Status> statuses = new ArrayList<Status>();
StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
statuses.add(status);
System.out.println(statuses.size() + ":" + status.getText());
int usersIndexed = cr.retrieve(status.getUser());
usersSaved = database.countDocuments();
twitterSearch.setOut("usersSaved: "+usersSaved);
if(usersIndexed > maxTweets || Stream.stopCrawl){
//ci.load();
ci.load(); //this call creates my index
twitterSearch.setOut("INDEX CREATED");
System.out.println("shutdown...");
twitterSearch.setOffAlreadyCrawling();
twitterStream.shutdown();
}
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
}
public void onScrubGeo(long userId, long upToStatusId) {
}
public void onException(Exception ex) {
ex.printStackTrace();
}
@Override
public void onStallWarning(StallWarning arg0) {
// TODO Auto-generated method stub
}
};
twitterStream.addListener(listener);
twitterStream.sample("en");
}
public void execute1(){
try{
this.execute();
}catch(TwitterException e){
e.printStackTrace();
}
}
public void run(){
try {
this.execute();
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
回答1:
When your thread is shut down/closed, it prevents it from being "restarted", as with other java IO classes. In other words, once you close it, you can't really start it up again. I'm pretty sure somewhere in either the Twitter code or your code, your thread is being stopped. To prevent this from happening, here's a code snippet that may work: http://pastebin.com/APByKuiY Also, try this stack overflow thingy: What could be the cause of RejectedExecutionException.
来源:https://stackoverflow.com/questions/35244234/why-java-util-concurrent-rejectedexecutionexception-using-twitter4j-to-sample-tw