Closed GitEngHar closed 6 months ago
## テンプレ用
### aaa
#### コード
◆aaa
```java
以下問題を解決する条件のことを スレッドセーフ
という
マルチスレッドを利用することは現場で恐れられているという
発生するエラーの多くが再現性がとれないもの
デッドロック問題のようにタイミングが重なって起きる問題で発生するからである
その為、安易にスレッド処理を作成してはならない
synchronized
は修飾子になっており、これを利用したメソッド内の実行はシングルスレッドのみとなり
複数スレッドで呼び出す際は同時実行できず、先に呼び出した処理が終了するまで待つ
synchronized void sycs(){}
クラス単位 (クラスないメソッドで同期を取る場合は以下に配慮する)
メソッド単位
synchronized
は スコープに配慮し利用するべき
スコープ内はシングルスレッドになるため、多用や広範囲での利用はスループットの低下となる
◆100万回の計算
public class Incrementer implements Runnable{
private String name;
private HolderInt holders;
public Incrementer(String name,HolderInt holder){
this.name = name;
this.holders = holder;
}
public void run(){
System.out.printf("[%s] started %n",name);
for(int i=0;i<1000000;i++){
holders.increment();
}
System.out.printf("[%s] started %n",name);
}
}
◆ インクリメントの実行
public class HolderInt {
private int intNum = 0;
public int getNum(){
return intNum;
}
public void increment(){
this.intNum++;
}
}
◆ 100万回 計算 を 2スレッドで並列実行
import java.util.List;
public class ResourceLock implements Runnable
{
private String name;
private List<String> fromList;
private List<String> toList;
public ResourceLock(String name,List<String> fromList, List<String> toList){
this.name = name;
this.fromList = fromList;
this.toList = toList;
}
public void run(){
String str = null;
try{
// %n は改行
System.out.printf("[%s] started.%n",name);
Thread.sleep(500L);
System.out.printf("[%s] attempt to lock fmList(%s).%n",name,fromList);
synchronized (fromList){
System.out.printf("[%s] fmList(%s) was locked.%n",name,fromList);
str = fromList.get(0);
System.out.printf("[%s] %s <- fmList(%s).%n",name,str,fromList);
Thread.sleep(500L);
System.out.printf("[%s] attempt to lock toList(%s).%n",name,toList);
synchronized (toList){
System.out.printf("[%s] toList(%s) was locked.%n",name,toList);
toList.add(str);
System.out.printf("[%s] %s -> toList(%s).%n",name,str,toList);
}
}
}catch(InterruptedException e){
e.printStackTrace();
} finally{
System.out.printf("[%s] finished.%n",name);
}
}
}
結果が200万にとどかない
[thread2] started
[thread1] started
[thread2] started
[thread1] started
result:1956006
put
や put
と remove
を繰り返すと無限ループが発生する可能性がある iterator
でリストを処理している最中に add
や remove
を対象リストに実施すると、Iterator
処理直前に ConcurrentModificationException
が発生する上記を避けるために、使用するクラスがスレッドセーフ を扱うかどうかを確認する必要がある
クラス変数 や インスタンス変数を持たないようにする
どうしても必要な場合にのみ、利用することでマルチスレッド問題を極力回避する
常に保持する必要のない変数はメソッドの引数に渡すようにする
◆ Before
public class Bedore(){
String name;
int old;
public void readyName(){
this.name = "haru";
this.old = 12;
hello();
}
public void hello(){
System.out.printf("%s : %d old",this.name,this.old);
}
}
◆ After
public class Bedore(){
public void readyName(String name , int old){
hello(name,old);
}
public void hello(String name , int old){
System.out.printf("%s : %d old",this.name,this.old);
}
}
ロジック処理そのものを非同期処理として実行する
◆ ロジックの操作
public static void callbackSample(){
ExecutorService executor = Executors.newSingleThreadExecutor();
AsyncProcess proc = new AsyncProcess(
new AsyncCallback() {
public void notify(String message){
System.out.println("callback message" + message);
executor.shutdown();
}
});
executor.execute(proc);
System.out.println("AsyncProcess is started.");
}
◆ ロジック処理
public class AsyncProcess implements Runnable {
private AsyncCallback callback;
public AsyncProcess(AsyncCallback callback){
this.callback = callback;
}
public void run(){
try{
Thread.sleep(1000);
this.callback.notify("Finished");
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("AsyncProcess finished");
}
}
◆ Interface
public interface AsyncCallback {
void notify(String message);
}
public static void futureSample(){
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<String> future = exec.submit(new Callable<String>() {
public String call(){
try{
Thread.sleep(1000);
}catch(InterruptedException ex){
return "Error";
}
return "Finished";
}
});
System.out.println("Exec Service is fanished");
try{
String message = future.get();
System.out.println("Exec is finished : message = " + message);
}catch(InterruptedException | ExecutionException ex){
ex.printStackTrace();
}finally{
exec.shutdown();
}
}
future.get 時に実行される
https://github.com/GitEngHar/learnJava/issues/1 上記に紐づく issue
検証ソースコード