2012-04-17 3 views
0

Я хочу сохранить объект (модель/данные моей игры) на диск, но по мере того, как игра может стать довольно большой - достаточно большой, чтобы взять несколько тиков игры для хранения - думая, что имеет смысл выполнять сохранение в отдельном потоке, чтобы поддерживать игру относительно плавно.Создание нового потока для сохранения объекта в файл

Каков наилучший способ достижения этого? Я не был уверен, имеет ли смысл сделать GameState (модель) runnable или расширение Thread, потому что большую часть времени он не предназначен для Runnable - логически, то это не должно быть Runnable?

Другие возможности, на которые я смотрел, - это класс Runnable GameSaver, которому я передаю GameState или копию GameState. Предположительно, однако, это вызовет проблемы с синхронизацией, если я передам GameState или замедлит игру, пока класс клонируется.

Каков наилучший подход, или подходы «за» и «против»? Любые другие альтернативы тоже оценили - я сомневаюсь, что мой поиск был исчерпывающим.

+0

Вы должны решить синхронизации, независимо от решения вы выбираете. – biziclop

+0

Я не вижу, как вы можете безопасно писать состояние, не делая моментального снимка. –

+0

@Martin James Это зависит от того, как организовано ваше государство. Если, например, вы храните события с меткой времени, вам это не нужно. (Думайте об игре в шахматы.) – biziclop

ответ

2

С точки зрения управления чистой нитью, самым чистым способом я считаю использование исполнителя. Это не решает проблему клонирования (или нет).

Создайте метод, который сохраняет игру:

public void saveTheGame() { 
    //you maybe need to take a snapshot, which might require synchronization 
    GameState state = ....; 
} 

создать работоспособный, как член экземпляра класса, например, что встраивает этот вызов и услуги исполнителя:

private final Runnable save = new Runnable() { 
    public void run() { 
     saveTheGame(); 
    } 
} 
private final ExecutorService executor = Executors.newFixedThreadPool(1); 

И спасти игра по мере необходимости:

executor.submit(save); 

Не забудьте выключить исполнителя, когда c потерять ваше приложение:

executor.shutdown(); 

Вы также можете использовать ScheduledExecutorService вместо этого запускается каждые х минут, например.

Класс может выглядеть следующим образом, например:

public static class GameSaver { 
    private final Runnable save = new Runnable() { 

     @Override 
     public void run() { 
      saveGame(); 
     } 
    }; 
    private static final ExecutorService executor = Executors.newFixedThreadPool(1); 
    private final GameState state; 

    public GameSaver(GameState state) { 
     this.state = state; 
    } 

    public void save() { 
     executor.submit(save); 
    } 

    public static void close() { 
     executor.shutdown(); 
    } 

    private void saveGame() { 
     //save your game here 
    } 

} 

и в основной код:

GameState state = getGameState(); 
GameSaver saver = new GameSaver(state); 
saver.save(); 
+0

Я полностью забыл о возможности создания Runnable внутри класса. Мне нужно взглянуть на ExecutorService, но это выглядит довольно аккуратно. Каковы преимущества этого, кроме аккуратности? –

+1

Вам не нужно иметь дело с деталями управления потоками низкого уровня - хотя вам все равно нужно иметь дело с синхронизацией, если это необходимо. Вы можете легко изменить пример и использовать «ScheduledExecutorService» для автоматического сохранения каждые x минут. – assylias

+0

Отлично, спасибо. Это выглядит очень аккуратным решением - теперь мне просто нужно решить, нужно ли делать снимок. –

Смежные вопросы