我正在研究訪問SQLite數據庫的應用程序。問題是數據庫在查詢時被鎖定。大多數情況下,這不是問題,因爲應用程序的流程非常線性。管理使用Java訪問數據庫的線程
但是我有一個很長的計算過程,這是由用戶觸發的。該過程涉及在計算之間對數據庫的多次調用。
我希望用戶獲得一些視覺反饋,所以我一直在使用Javafx progressIndicator和Javafx.Concurrency框架中的服務。 問題是這使得用戶可以隨意移動應用程序,並可能觸發對數據庫的其他調用。
這導致數據庫文件被鎖定的異常。 我想要一種方法來阻止該線程在運行時停止運行,但是我一直無法在線找到任何明確的例子。他們中的大多數都過於簡化,我想要一種可擴展的方式。我試過使用cancel()方法,但這並不能保證線程將被及時取消。
因爲我無法檢查isCancelled的代碼的所有部分,有時在線程被取消的時間和它有效停止的時間之間會有延遲。
所以我想到了下面的解決方案,但我想知道是否有更好的方法在效率和避免競賽條件和掛。
// Start service
final CalculatorService calculatorService = new CalculatorService();
// Register service with thread manager
threadManager.registerService(CalculatorService);
// Show the progress indicator only when the service is running
progressIndicator.visibleProperty().bind(calculatorService.runningProperty());
calculatorService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent workerStateEvent) {
System.out.println("SUCCEEDED");
calculatorService.setStopped(true);
}
});
// If something goes wrong display message
calculatorService.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent workerStateEvent) {
System.out.println("FAILED");
calculatorService.setStopped(true);
}
});
// Restart the service
calculatorService.restart();
這是一個我已經子類,包括可以用來設置該服務的狀態的方法我的服務類(停止或不停止)
public class CalculatorService extends Service implements CustomService {
private AtomicBoolean stopped;
private CalculatorService serviceInstance;
public FindBundleService() {
stopped = new AtomicBoolean(false);
instance = this;
}
@Override
protected Task<Results> createTask() {
return new Task<Result>() {
@Override
protected Result call() throws Exception {
try {
Result = calculationMethod(this, serviceInstance);
return Result;
} catch (Exception ex) {
// If the thread is interrupted return
setStopped(true);
return null;
}
}
};
}
@Override
public boolean isStopped() {
return stopped.get();
}
@Override
public void setStopped(boolean stopped) {
this.stopped.set(stopped);
}
}
服務實現了這個接口,我定義爲
public interface CustomService {
/**
* Method to check if a service has been stopped
*
* @return
*/
public boolean isStopped();
/**
* Method to set a service as stopped
*
* @param stopped
*/
public void setStopped(boolean stopped);
}
所有服務都必須向線程管理器註冊自己,該線程管理器是單例類。
public class ThreadManager {
private ArrayList<CustomService> services;
/**
* Constructor
*/
public ThreadManager() {
services = new ArrayList<CustomService>();
}
/**
* Method to cancel running services
*/
public boolean cancelServices() {
for(CustomService service : services) {
if(service.isRunning()) {
((Service) service).cancel();
while(!service.isStopped()) {
// Wait for it to stop
}
}
}
return true;
}
/**
* Method to register a service
*/
public void registerService(CustomService service) {
services.add(service);
}
/**
* Method to remove a service
*/
public void removeService(CustomService service) {
services.remove(service);
}
}
在應用程序的任何地方,如果我們想要停止服務,我們調用cancelServices()。這將設置狀態爲取消我正在檢查我的計算方法()然後設置狀態停止之前返回(有效地結束線程)。
if(task.isCancelled()) {
service.setStopped(true);
return null;
}
的分貝爲什麼多個呼叫?爲什麼不能在一次通話中獲得所有你需要的信息? – Sedrick
那是因爲我們正在根據從數據庫收到的內容進行一些計算,然後使用結果從數據庫中獲取其他內容。它是我不能改變的商業邏輯。 – user3552551
我會禁用所有'節點',這將觸發另一個調用數據庫,直到'任務'完成。 – Sedrick