[英]How to keep track of seconds?
我正在構建Java應用程序,需要跟蹤距程序開始已經過去了幾秒鍾。 我正在嘗試通過線程來實現這一目標,所以我有一個主類創建timeController
線程,等待5秒然后停止它,出於測試目的, timeController
現在唯一要做的就是打印經過的秒數每0.5秒。 但是請記住,我的最終目標是讓另一個對象的多個線程以同步的方式向timeController
詢問經過的秒數。 現在它只打印第一個Calendar.SECOND
並且從不更新該值,因為它在中斷之前運行了5秒鍾,並且每半秒更新一次,所以我希望看到類似44 44 45 45 46 46 47 47 48 48的內容(假設系統啟動時的秒數是44)。 謝謝。
public class Main {
public static void main(String[] args) {
TimeController timeCon = TimeController.getInstance();
timeCon.start();
try {
Thread.sleep(5000);
timeCon.stop();
} catch (Exception e){
//ignore for now
}
}
}
public class TimeController implements Runnable{
private static TimeController instance = null;
private volatile Thread timeCon;
private Calendar calendarInstance = Calendar.getInstance();
private int secondsElapsed = 0;
private int incialSeconds = 0;
public int getElapsedSeconds(){
return secondsElapsed;
}
public static TimeController getInstance(){
if(instance == null){
instance = new TimeController();
}
return instance;
}
public void start(){
timeCon = new Thread(this);
timeCon.start();
}
public void stop(){
timeCon = null;
}
@Override
public void run() {
Thread thisThread = Thread.currentThread();
while (thisThread == timeCon) {
try {
Thread.sleep(500);
secondsElapsed = calendarInstance.get(Calendar.SECOND) - incialSeconds;
System.out.println(getElapsedSeconds());
} catch (Exception e){
//Ignore for now.
}
}
}
}
目前,它僅打印第一個Calendar.SECOND,並且從不更新該值
您似乎想為您的計時問題提供並發解決方案,但是計時線程中的所有代碼都沒有同步。 至少該塊是可疑的:
private Calendar calendarInstance = Calendar.getInstance();
private int secondsElapsed = 0;
private int incialSeconds = 0;
public int getElapsedSeconds(){
return secondsElapsed;
}
這里沒有進行同步。 由於線程可能在具有不同本地緩存的不同內核上執行,因此無法保證對在不同處理器內核上執行的另一個線程可見對一個線程中的變量所做的更改。 這可能就是您的代碼中正在發生的事情。
您將需要仔細定義可變對象(這里為TimerController)的狀態空間,並實現對您的用例有意義的線程安全策略。 您的策略的目標是防止對象的可變狀態遭受導致活動性和安全性失敗的競爭狀況(即,防止無效的狀態轉換)。 解決此問題的常用方法是使用監視模式,通過使用鎖來實現互斥和可見性。
您應該在需要時, 每次需要時以及僅在需要時才在與主代碼相同的線程中計算經過時間。 不需要單獨的線程不斷計算和存儲經過的時間值。
謝謝所有嘗試提供幫助的人,雖然將來當多個線程嘗試從TimeController中獲取時間時會出現同步問題,但對於這種特殊情況並非如此。 我發現問題在於,我確實應該在run方法內部使用Calendar.getInstance()來更新每次運行的引用時,仍然保留對Calendar的靜態引用。 這是它的外觀:
@Override
public void run() {
Thread thisThread = Thread.currentThread();
while (thisThread == timeCon) {
try {
Thread.sleep(500);
secondsElapsed = Calendar.getInstance().get(Calendar.SECOND) - incialSeconds;
} catch (Exception e){
//Ignore for now.
}
}
}
您可以將班級替換為
public enum TimeController {
INSTANCE;
final long started = System.currentTimeMillis();
public int getElapsedSeconds() {
return (System.currentTimeMillis() - started) / 1000;
}
@Deprecated
public static TimeController getInstance() {
return INSTANCE;
}
}
甚至更簡單
public enum TimeController {
;
static final long started = System.currentTimeMillis();
public static int getElapsedSeconds() {
return (System.currentTimeMillis() - started) / 1000;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.