Hatena::ブログ(Diary)

あおうさ@日記 このページをアンテナに追加 RSSフィード Twitter

「私は、いつかコードで人を感動させる。そう、音楽や映画やスポーツで私を感動させたように・・・」 「この思いは絶対に忘れない。」

2009-10-08

[]gmailをよく使う人はChromeのアプリケーションショートカットを作っておくと便利 11:10 gmailをよく使う人はChromeのアプリケーションショートカットを作っておくと便利を含むブックマーク gmailをよく使う人はChromeのアプリケーションショートカットを作っておくと便利のブックマークコメント

Gmailをよく利用する方は、Gmailのアプリショートカットを作っておくと便利です。 わざわざブラウザを開かなくても、一瞬でGmailにアクセスできます。

私が Firefox から Chrome に乗り換えた7つの理由*二十歳街道まっしぐら

やってみましたが便利です。メーラーの為にChromeをインストールするというのが当たり前になりそうだ。まさにChromeOSが目指しているところなのか。


追記

コメントを頂いたのでこれについて思うところを書く。


まず、何が便利なのかというと「タブ欄などがなくなりウインドウがすっきり」という表現になる。これだけだとそれだけで便利?となりがちかもしれない。しかし、私はこれをみた時にこう思った。もうすぐ来たるhtml5時代に備えてchromeはこうきたかと。どういうことかと言うと、gmailchromeでショートカット作成するとgmailのアイコンでショートカットができる。そして、そのショートカットから起動した場合はタブ欄などはなくなりウインドウを最大限に使える。まさにデスクトップアプリのように使えるということなのだ。これをアプリと捉えるとgmailのショートカットを作るだけでメーラーをインストールしたことになる。ここで何げに重要なのがショートカットのアイコンまで変わること。これがアプリケーションなんだよと

主張している。恐らくあと数ヶ月でhtml5を使ったゲームなどが出てくると思うがインストールと題してショートカットを作るのが一般的になるのではないかと感じている。ここまで浸透するとページを開くという感覚からアプリを起動するという感覚へ変わる。そうなってくる,としめたものだ。複雑なアプリの起動には多少時間がかかるものだがショートカット起動時にローディング画面を用意してもアプリを起k動する感覚なのでイライラは軽減されるだろう。こんなことをあれこれ考えていて、超略して便利という言葉を使った。質問の回答になっただろうか?

[]appengine用のMemcacheCounterを作ったので紹介 22:17 appengine用のMemcacheCounterを作ったので紹介を含むブックマーク appengine用のMemcacheCounterを作ったので紹介のブックマークコメント

仕組みは以前書いたこの方法

        MemcacheService s = MemcacheServiceFactory.getMemcacheService();
        if (!s.contains("MemcacheCounter")) {
            s.put("MemcacheCounter", 1); // 初期化は1
        } else {
            s.increment("MemcacheCounter", 1); // 2回目以降は値に+1する
        }
        System.out.println(s.get("MemcacheCounter")); // 実行のたびに1,2,3,4,5になる
GAE/J Memcacheの低レベル APIを使ってカウンターを作る

MemcacheCounterの使い方

        MemcacheCounter counter = MemcacheCounter.getCounter("TestCounter");
        counter.countUp();   // 1
        counter.countUp();   // 2
        counter.countDown(); // 1
        counter.getCount();  // 1
        counter.clear();     // 0

※なんらかの理由でキャッシュがクリアされた場合は0に戻ります。

 短期間のカウンターに使ってます。

MemcacheCounter.class

import java.util.logging.Logger;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.apphosting.api.ApiProxy;

public class MemcacheCounter {

    private static final Logger logger = Logger.getLogger(MemcacheCounter.class.getName());

    private static final String KEY_PREFIX = ApiProxy.getCurrentEnvironment().getVersionId() + ".MemcacheCounter.";

    private String key;

    private MemcacheCounter(String key) {
        this.key = KEY_PREFIX + key;
    }

    private static MemcacheService service =
        MemcacheServiceFactory.getMemcacheService();

    public synchronized static MemcacheCounter getCounter(String key) {
        MemcacheCounter counter = new MemcacheCounter(key);
        if (!counter.initialized()) {
            counter.initialize();
        }
        return counter;
    }

    private boolean initialized() {
        return service.contains(key);
    }

    private void initialize() {
        logger.info("call initialize"); // ※キャッシュが突然消失してしまった場合もinitializeが実行されるので0に戻る
        service.put(key, new Long(0));
    }

    public long getCount() {
        if (!canGetCount()) {
            throw new NullPointerException("MemcacheCounter.getCount is null");
        }
        Long count = (Long) service.get(key);
        return count;
    }

    public long countUp() {
        if (!canGetCount()) {
            throw new NullPointerException("MemcacheCounter.countUp is null");
        }
        return service.increment(key, new Long(1));
    }

    public long countDown() {
        if (!canGetCount()) {
            throw new NullPointerException("MemcacheCounter.countDown is null");
        }
        return service.increment(key, new Long(-1));
    }

    public void clear() {
        service.put(key, new Long(0));
    }

    private boolean canGetCount() {
        return service.contains(key);
    }
}

[]appengineでMemcacheを使ったLockを実装した 22:32 appengineでMemcacheを使ったLockを実装したを含むブックマーク appengineでMemcacheを使ったLockを実装したのブックマークコメント

id:kazunori_279さんのMemcacheでスピンロックを実装してTask Queue処理結果を集約してみるテスト - スティルハウスの書庫が便利な仕組みなので実装してみた。実はこれを実装するのに前エントリのMemcacheCounterを使っているのでそれもエントリした。

MemcacheLockの使い方

手動でロックする場合
        MemcacheLock lockObj = new MemcacheLock("Counter.countUp");
        lockObj.lock();
        try {
            Counter c = new Dao().from(Counter.class).getFirstResult();
            c.setCount(c.getCount() + 1);
            makePersistentInTx(c);
        } finally {
            lockObj.unLock();
        }
自動でロックする場合

こちらは「ロック取得に失敗しても、何回かはリトライしたい」を実装してあります。

10回ロックを取得して失敗した場合はExceptionをthrowしてロックを解放します。

        new MemcacheLock("Counter.countUp").runSynchronized(new Runnable() {
            public void run() {
                Counter c = new Dao().from(Counter.class).getFirstResult();
                c.setCount(c.getCount() + 1);
                makePersistentInTx(c);
            }
        });

MemcacheLock.class

import java.util.logging.Logger;

import org.slim3.util.ThrowableUtil;

/**
 * Memcacheを使用してロックを実現する
 */
public class MemcacheLock {

    @SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(MemcacheLock.class.getName());
    private static final String KEY_PREFIX = "MemcacheLock.";

    @SuppressWarnings("unused")
    private static final long UNLOCKED = 0;
    private static final long LOCKED = 1;

    private MemcacheCounter counter = null;

    private boolean isLocked = false;

    public MemcacheLock(String key) {
        this.counter = MemcacheCounter.getCounter(KEY_PREFIX + key);
    }

    public boolean lock() {
        if (isLocked) {
            return true;
        }
        if (counter.countUp() == LOCKED) {
            isLocked = true;
            return true;
        }
        counter.countDown();
        return false;
    }

    public void unLock() {
        if (isLocked) {
            counter.countDown();
            isLocked = false;
        }
    }

    public void runSynchronized(Runnable runner) {
        for (int i = 0; i < 10; i++) {
            if (!lock()) {
                if (i == 9) {
                    // リトライをあきらめて例外
                    throw new RuntimeException("MemcacheLock.runSynchronized");
                }
                sleep();
                continue;
            }
            try {
                runner.run();
                return;
            } catch (Throwable t) {
                ThrowableUtil.wrapAndThrow(t);
            } finally {
                this.unLock();
            }
        }
    }

    private void sleep() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException t) {
            ThrowableUtil.wrapAndThrow(t);
        }
    }
}

お願い

ソース読んでバグぽいところがあったら教えてください。多数のリクエストを実行してカウントが取れることはテストしたのですが、こういう処理はバグが見えにくくて。。。

fumokmmfumokmm 2009/10/09 02:58 私もショートカットをつくってありますが、ブラウザのタブで開くのとそう大差ないなと感じております。どのあたりが便利ですか?