I have search as you type functionality although it searches very fast and I can't notice it even with no multithreading I still want to know how would I use multithreading on this
search.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s2) {
manager.searchString(s2);
listView.getItems().setAll(manager.getList());
}
});
So basically there is a TextField
that when its text is changed I go and call a search method in object manager
which puts its search result in an array when it finishes.
Then the ListView
should update its data to this new array when it finishes.
How can I make the search on one thread and when it finishes it update the list data?!
I believe I can't just call the list function from other thread because GUI stuff should be called from only one thread.
To do this efficiently in a different thread is not as simple as it sounds.
You don't want to create and execute a new thread every time a key is pressed because:
You could use a single-thread executor service (which keeps one thread alive and uses it to execute Runnables passed into it in order), which would be more efficient, but you'd need to remember to shut it down when your text field is destroyed (if you do ever destroy your text field). Something along these lines:
// first of all, at the class level (assuming listView and manager are both class-level variables, preferably final ones, too):
// An INNER class implementing Runnable which will carry out the searching
private class Searcher implements Runnable {
private volatile boolean cancelled = false;
private final String searchTerm;
Searcher(String searchTerm) {
this.searchTerm = searchTerm;
}
public void cancel() {
cancelled = true;
}
@Override
public void run() {
// remember that there's no guarantee that this will execute before the NEXT keypress, so we add a check to ensure that we still want to perform the search when it gets executed:
if (!cancelled) {
manager.searchString(searchTerm);
Platform.runLater(listViewUpdater); // listViewUpdater is defined below
}
}
}
// a Runnable to actually update the GUI after a seach has been performed
private Runnable listViewUpdater = new Runnable(){
@Override
public void run() {
listView.getItems().setAll(manager.getList());
}
}
private ExecutorService executor = Executors.newSingleThreadExecutor();
private Searcher lastSearcher = null;
// ... then, in the method which sets up the GUI
search.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s2) {
if (lastSearcher != null) {
lastSearcher.cancel(); // prevents lastSearcher from running if it hasn't done so already
}
lastSearcher = new Searcher(s2);
executor.submit(lastSearcher);
}
});
The downside is you are creating a new object every time the value changes, but that isn't nearly as bad as creating a new Thread every time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.