2017-04-04 122 views
0

下面的類會更新特定時間間隔內的地圖。線程需要等待列表更新

public class CheckerThread extends Thread { 

    private volatile HashMap<String, Integer> map = new HashMap<>(); 

    @Override 
    public void run() { 
      while (true) { 
       updateMap(); 
      try { 
      Thread.sleep(1000); 
      } 
      catch (InterruptedException e) { 
      // Do something 
      } 
      } 
    } 

    private void updateMap() { 
    HashMap<String, Integer> localMap = new HashMap<>(); 
    int count = 0; 
    while (count < 10) { 
     localMap.put(count + "a", count); 
     count++; 
    } 
     this.map = localMap; 
    } 


    public Map<String, Integer> getMap() { 
    return this.map; 
    } 
} 

下面的Class調用方法getMap()來獲取Map。在返回類「CheckerThread」中的地圖之前,我需要確保列表完全更新。該方法應該等到地圖更新。

public class GetterThread extends Thread { 

private final CheckerThread checkerThread; 

public GetterThread(final CheckerThread checkerThread) { 
    this.checkerThread = checkerThread; 
    } 

    @Override 
    public void run() { 
     System.err.println(this.checkerThread.getMap()); 
    } 
    } 

另一個類Main創建線程。

public class MainThread extends Thread { 
public static void main(final String[] args) throws InterruptedException { 
    int i = 0; 
    GetterThread[] getterThreads = new GetterThread[5]; 
    CheckerThread checkerThread = new CheckerThread(); 
    checkerThread.start(); 
    while (i < 5) { 
     getterThreads[i] = new GetterThread(checkerThread); 
     getterThreads[i].start(); 
     Thread.sleep(1000); 
     i++; 
    } 
    } 
} 
} 
+0

答案必須使用自定義類還是可以使用Java標準API中的類? (另外,絕對不要忽略'InterruptedException'。) – markspace

+0

你永遠不會在你的'updateMap'方法中增加'count'變量,它將永遠運行 –

+0

這不是實際的代碼。這只是功能的概述。所以忽略數量和例外。無論如何謝謝你的更正。 – prithivraj

回答

1

一個線程的想法是確定爲,但沒有足夠的(其中大部分是因爲線程不他們做後的工作...返回任何東西),如果你想仍使用線程,那麼你將結束在等待/加盟/通知的方式...

可以代替thread --> runnable使用task --> callable

可調用是對類固醇的線程,可以在的ExecutorService執行它們,等到這份工作不是é甚至得到一個結果,讓你知道,如果一切順利或不!

藉此作爲一個例子並參考文檔的詳細資料:

public class _Foo { 

    public static void main(String... args) throws InterruptedException, ExecutionException { 
     ExecutorService exService = Executors.newSingleThreadExecutor(); 
     FutureTask<Boolean> futureTask = new FutureTask<>(new MapCleaner()); 
     exService.execute(futureTask); 
     System.out.println("Was everything ok??: " + futureTask.get()); 
    } 
} 

class MapCleaner implements Callable<Boolean> { 
    @Override 
    public Boolean call() { 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      System.out.println(ex); 
     } 
     return System.currentTimeMillis() % 2 == 0; 
    } 
} 
0

你看過期貨嗎? Future.get()等待任務完成。這可能是你需要的嗎?

public class MyCallable implements Callable<Map<String, Integer>> { 

    private volatile HashMap<String, Integer> map = new HashMap<>(); 
    private boolean wait = true; 

    public void call() { 
     while (wait) { 
      updateMap(); 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 

      } 
     } 
     return map; 
    } 

    private void updateMap() { 
     HashMap<String, Integer> localMap = new HashMap<>(); 
     int count = 0; 
     while (count < 10) { 
      localMap.put(count + "a", count); 
     } 
     this.map = localMap; 
     wait = false; 
    } 

} 

,並根據您的例子未來

ExecutorService executor = Executors.newSingleThreadExecutor(); 
Future<Map<String, Integer>> future = executor.submit(new MyCallable()); 
// Future.get() waits for task to get completed 
Map<String, Integer> myMap = fut.get(); 
0

只是打電話,我想你應該使用BlockingQueue。將元素放入「檢查器」線程的隊列中,並在「getter」線程中使用阻塞等待來讀取它們。這很容易,很乾淨,不需要太多的改變。

一個隊列將爲您解決不僅同步問題,而且時間問題。無論您的線程運行的順序如何,您的getter線程都會一直等待,直到數據可用,然後返回。這幾乎是防彈的。

順便說一句,你有一個錯誤在你的檢查線程。你在地圖中放置了十個元素,但是你永遠不會增加count,這樣循環就永遠不會退出(它將無限數量的元素放入地圖中,最終會出現內存不足的錯誤)。

此外,永遠不會忽略和忽略InterruptedException。如果你被打斷,你幾乎總是想退出你的線程。 C.F. Brian Goetz的書Java Concurrency in Practice瞭解更多。

public class SimpleThreading 
{ 
    public static void main(String[] args) throws InterruptedException { 
     MainThread.main(args); 
    } 
} 

class MainThread extends Thread 
{ 

    public static void main(final String[] args) 
      throws InterruptedException 
    { 
     int i = 0; 
     GetterThread[] getterThreads = new GetterThread[ 5 ]; 
     CheckerThread checkerThread = new CheckerThread(); 
     checkerThread.start(); 
     while(i < 5) { 
     getterThreads[i] = new GetterThread(checkerThread); 
     getterThreads[i].start(); 
     Thread.sleep(1000); 
     i++; 
     } 
    } 
} 

class GetterThread extends Thread 
{ 

    private final CheckerThread checkerThread; 

    public GetterThread(final CheckerThread checkerThread) 
    { 
     this.checkerThread = checkerThread; 
    } 

    @Override 
    public void run() 
    { 
     try { 
     System.out.println("waiting..." + checkerThread.getQueue()); 
     System.err.println(this.checkerThread.getQueue().take()); 
     } catch(InterruptedException ex) { 
     // exit on interrupt 
     } 
    } 
} 

class CheckerThread extends Thread 
{ 

    private HashMap<String, Integer> map; 
    private final BlockingQueue<Map<String,Integer>> queue = 
      new LinkedBlockingQueue<>(); 

    @Override 
    public void run() 
    { 
     while(true) 
     try { 
      updateMap(); 
      queue.put(map); 
      System.out.println("Added " + map); 
      Thread.sleep(1000); 
     } catch(InterruptedException e) { 
      return; // exit on interrupt 
     } 
    } 

    private void updateMap() 
    { 
     HashMap<String, Integer> localMap = new HashMap<>(); 
     int count = 0; 
     while(count < 10) 
     localMap.put(count + "a", count++); 
     this.map = localMap; 
    } 

    public BlockingQueue<Map<String, Integer>> getQueue() 
    { 
     return queue; 
    } 
} 
+0

這不是實際的代碼。這只是功能的概述。所以忽略數量和例外。無論如何謝謝你的更正。 – prithivraj