2009年12月3日木曜日

ThreadPoolとThreadLocalを併用する際の注意

ThreadLocalは便利だけど実は落とし穴ががが

TomcatなどのThreadPoolを使用する場合、同一のThreadが使いまわされるため、
ThreadLocalの値も引き継がれてしまうという現象が起き、それがもとでエラーが発生することが。。。

以下その検証コード

public static void main(String[] args){

System.out.println("hoge");


threadLocal = new ThreadLocal();
executor = java.util.concurrent.Executors.newFixedThreadPool(3);
for(int i = 0;i < 10;i++)
{
executor.execute(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String value = threadLocal.get();
if(value == null){
value = new Random().nextInt() + "";
threadLocal.set(value);
}

System.out.println(value);

}
});


}

}
}





結果として、全て違う値が表示されることが期待されるが、
実際は同じ値がなんども表示される。
そのため、Threadの終了時に

ThreadLocal.remove();

を明示的に呼び出すようにしてやることをお勧めします。

2009年9月1日火曜日

Scala LiftでLocのコンストラクタが変わってる

Getting startedとかでは、BootクラスのentriesにSiteMapを追加するのに
val entries = 
Menu(Loc("Home", "/", "Home")) :: Nil


みたいに紹介されてるけど、バージョンアップによりコンストラクタが変更されてるためにコンパイルが通らない状態になってるみたい。
第二引数がStringからListに代わってるだけなので以下のうようにするだけでOK

val entries = 
Menu(Loc("Home", List(""), "Home")) :: Nil


また、"/hoge/fuga"のようなサイトマップを追加したい場合は

val entries = 
Menu(Loc("Home", List("hoge","fuga"), "Home")) :: Nil

とするだけでいいぽ

2009年8月31日月曜日

JUnit assertThat用のBetweenクラスを作ってみた

JUnitのassertThatで有効範囲を指定してテストを行うためのクラスを作った

使い方は


Assert.assertThat(2,Between.between(1,4));



みたいな感じ


以下コード



import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
/**
* Comparableなものをが特定の範囲内の値であるかどうかを判定する
* @author takeshita
*
*/
public class Between extends BaseMatcher<Comparable>{

/**
* lower <= value <= upper
* @param lowerLimit
* @param upperLimit
* @return
*/
public static Between between(Comparable lowerLimit ,Comparable upperLimit)
{
return between_UE_LE(lowerLimit,upperLimit);
}
/**
* lower < value < upper
* @param lowerLimit
* @param upperLimit
* @return
*/
public static Between between_UT_LT(Comparable lowerLimit ,Comparable upperLimit)
{
return new Between(lowerLimit,upperLimit,0,0);
}
/**
* lower <= value < upper
* @param lowerLimit
* @param upperLimit
* @return
*/
public static Between between_UE_LT(Comparable lowerLimit ,Comparable upperLimit)
{
return new Between(lowerLimit,upperLimit,1,0);
}
/**
* lower < value <= upper
* @param lowerLimit
* @param upperLimit
* @return
*/
public static Between between_UT_LE(Comparable lowerLimit ,Comparable upperLimit)
{
return new Between(lowerLimit,upperLimit,0,-1);
}

/**
* lower <= value <= upper
* @param lowerLimit
* @param upperLimit
* @return
*/
public static Between between_UE_LE(Comparable lowerLimit ,Comparable upperLimit)
{
return new Between(lowerLimit,upperLimit,1,-1);
}


Comparable lowerLimit ,upperLimit;
int lowerThreshold = 0,upperThreshold = 0;
private Between(Comparable lowerLimit ,Comparable upperLimit,
int lowerThreshold,int upperThreshold)
{
this.lowerLimit = lowerLimit;
this.upperLimit = upperLimit;
this.lowerThreshold = lowerThreshold;
this.upperThreshold = upperThreshold;
}



@Override
public boolean matches(Object obj) {
return lowerLimit.compareTo(obj) < lowerThreshold &&
upperLimit.compareTo(obj) > upperThreshold;
}



@Override
public void describeTo(Description desc) {
desc.appendText(
lowerLimit.toString() +
(lowerThreshold == 0 ? " < value " : " <= value ") +
(upperThreshold == 0 ? "< " : "<= ") +
upperLimit.toString());

}
}

はじめまして

自分用の備忘録ブログ

public class Main{
public static void main(String[] args){

}
}