株式会社後藤広一 ソフトウェア開発
システムインテグレータ 株式会社後藤広一
javascript let の可読性の無いソースコードは避けるべき。
javascriptのvarは推奨されておりませんが、varの宣言をletに単純に置換するとバグに繋がります。
letは再宣言不可能なので、予期せぬ動作に繋がります。
以下はバグが発生し易いソースコードの例です。
let x = 10;
{
let x = 20; // このブロック内では新しい変数として扱われる
console.log(x); // 20
}
console.log(x); // 10
昔勤務していたコンピュータ会社で2000年問題の対応をしました。100年に一度、閏年ではない年がやって来るそうです。
ちなみに2100年は閏年(うるうどし)ではありません。
2100年問題 例:
権利確定日は「29日」の場合があります。
令和5年の権利確定日は「2月28日、3月31日」です。
来年令和6年の権利確定日は「2月29日、3月29日」です。
2100年の権利確定日は「2月26日、3月31日」です。
固定データでもいいので対応しておいた方がいいかもしれません。
コンピュータプログラムのバグ(プログラムミス)のパターン
2023年11月28日
「AでもBでもない」は「Not A or Not B (!A || !B)」ではなくて「Not A and Not B (!A && !B)」
※このプログラムのケースは非常にヤバイ!なにがヤバイっていうとテストケースの漏れがある可能性があるので、その影響でメモリ領域解放のタイミングがなくなるとヤバイ。
自動ではコードチェックが出来ないソースの例
自動ではコードチェックが出来ないソースの例
オーバロード、オーバライド時の同じローカル変数を間違えると誤操作確定。
エクリプスを使用しても正常なソースとして認識されます。
目視でソースコードをレビューするしかありません。ちゃんと眠りましょう。
プログラミング教室
(C言語)
C言語で一番難しいのはポインタです。逆にポインタを理解し、メモリ破壊を起こさない(※1)様にすれば即刻プロ級です。
The most difficult thing about C is pointers. On the other hand, if you can understand pointers and avoid memory corruption (※1), you will quickly become a pro.
1.C言語のポインタ変数はメモリ領域(静的もしくは動的)のアドレスを格納するためのサイズしか無い(ハード毎で同一サイズ)ことに注意して下さい。
2.*が付くポインタ変数は、通常の変数と違いアドレスしか格納できないことに注意して下さい。
1. C pointer variables are only large enough to store the address of a memory area (static or dynamic) (the size is the same for each hardware).
2. Please note that pointer variables with * can only store addresses, unlike normal variables.
(プログラムコード例)
型宣言(構造体含む) *ポインタ変数;
ポインタ変数 = &(メモリ領域、配列等) もしくは アドレス
&はアドレスを意味します。
(※1)ポインタ変数は必ず初期化(アドレスを格納)して、メモリ領域のサイズを意識してプログラミングしている事を確認しましょう。
(Program code example)
Type declaration (including structures) * pointer variable;
Pointer variable = & (memory area, array, etc.) or address
& means address.
(※1) Always initialize pointer variables (save the address) and program taking into account the size of the memory area.
java開発環境(gotohirokazu.netの場合の例) ー 現在、Windowsツール‐コマンドプロンプト(MS-DOS)で開発中。
java動作環境 スタートメニュー すべて>Windows ツール システム
コントロール パネル\システムとセキュリティ\Windows ツール
コマンドプロンプト上で動作。
「コマンドプロンプト」アイコン(ターミナルに似ているアイコン)右クリックでショートカットを作成して下さい。
ショートカット起動後は下記、 実行結果※1 参照(Enterキーを押すと改行します)。
全て同一ディレクトリ内で可
ダウンロードjdk
ファイル構成
javacompile.bat
net\SystemLog_Monitor.java
net\SearchSignInAccount_Goto.java
net\SystemThread_Goto.java
net\HardPassword_Goto.java
net\ToStringInstance_Goto.java
net\AuthenticationInterface_Goto.java
net\Authentication_Goto.java
javacompile.bat
set path = C:\Program Files\Java\jdk-23\bin;
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\SystemLog_Monitor.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\SystemThread_Goto.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\SearchSignInAccount_Goto.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\HardPassword_Goto.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\ToStringInstance_Goto.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\AuthenticationInterface_Goto.java
javac -Xlint:unchecked -Xlint:preview --enable-preview --release 23 -g net\Authentication_Goto.java
仕様書
//ログの出力先をWindowsインストール先ドライブ(C:)以外にする。
//ログを出力するファイルの容量が増えるとそれを表示するためのメモリ領域を圧迫する可能性があるため。
//本ソフトウェアのインストール先は、USBメモリ等の外部ストレージが望ましい。(開発環境はC:ドライブ)
//ログの出力イメージはjavaデザインパターンのAbstructFactoryパターン
実行結果※1
Microsoft Windows [Version 10.0.26100.2605]
(c) Microsoft Corporation. All rights reserved.
C:\Users\後藤広一>cd java
C:\Users\後藤広一\java>java net\SystemLog_Monitor.java
SystemLog_Monitorクラスはまだ未実装ですが、System.outとロガー出力を実装しようと思います。
C:\Users\後藤広一\java>
SystemLog_Monitor.java
package net;
import net.SystemLog_Monitor;
/* SystemLog_Monitor javadoc (未実装)*/
//モニター出力、ロガー出力クラス
public class SystemLog_Monitor {
public static void syslog_moni(String log_monitor) {
System.out.println(log_monitor);
}
public static void main(String[] args) {
SystemLog_Monitor.syslog_moni("SystemLog_Monitorクラスはまだ未実装ですが、System.outとロガー出力を実装しようと思います。");
}
}
AuthenticationInterface_Goto.java
package net;
import net.AuthenticationInterface_Goto;
/* AuthenticationInterface_Goto javadoc (未実装)*/
//認証インターフェース
public interface AuthenticationInterface_Goto {
/**
* Basic認証:ユーザー名とパスワードを使用するシンプルな方式。
* @return Basic認証でユーザが存在した場合、Boolean.TRUEを返却する。
*/
public Boolean isBasicAuthentication();
/**
* APIキー認証:API提供者が発行する固有のキーを使用する方式。
* @return SystemLog_Monitorが使用可能の場合、Boolean.TRUEを返却する。
*/
public Boolean isApikeyAuthentication();
/**
* OAuth認証:ユーザーがアプリケーションに特定の権限を与える方式。
* @return OAuth認証が認可の場合、Boolean.TRUEを返却する。
*/
public Boolean isOAuthentication();
/**
* Tokenベース認証:事前に取得したトークンを使用する方式。
* @return Tokenベース認証でチェック同一の場合、Boolean.TRUEを返却する。
*/
public Boolean isTokenBaseAuthentication();
}
Authentication_Goto.java
package net;
import net.AuthenticationInterface_Goto;
import net.Authentication_Goto;
/* AuthenticationInterface_Goto javadoc (未実装)*/
//認証クラス
public class Authentication_Goto implements AuthenticationInterface_Goto {
/**
* Basic認証:ユーザー名とパスワードを使用するシンプルな方式。
* @return Basic認証でユーザが存在した場合、Boolean.TRUEを返却する。
*/
public Boolean isBasicAuthentication(){
synchronized(this){
return Boolean.TRUE;
}
}
/**
* APIキー認証:API提供者が発行する固有のキーを使用する方式。
* @return SystemLog_Monitorが使用可能の場合、Boolean.TRUEを返却する。
*/
public Boolean isApikeyAuthentication(){
synchronized(this){
return Boolean.TRUE;
}
}
/**
* OAuth認証:ユーザーがアプリケーションに特定の権限を与える方式。
* @return OAuth認証が認可の場合、Boolean.TRUEを返却する。
*/
public Boolean isOAuthentication(){
synchronized(this){
return Boolean.TRUE;
}
}
/**
* Tokenベース認証:事前に取得したトークンを使用する方式。
* @return Tokenベース認証でチェック同一の場合、Boolean.TRUEを返却する。
*/
public Boolean isTokenBaseAuthentication(){
synchronized(this){
return Boolean.TRUE;
}
}
}
SearchSignInAccount_Goto.java
package net;
import java.util.Vector;
import net.SystemLog_Monitor;
import net.SystemThread_Goto;
import net.SearchSignInAccount_Goto;
/* SearchSignInAccount_Goto javadoc (未実装)*/
//クライアントスレッドインスタンスをObject継承クラス内で管理している。
//クラス内でクライアントの情報を保持。
public class SearchSignInAccount_Goto {
//スレッドインスタンス
private SystemThread_Goto threadInstance = null;
private static Vector clientVector = new Vector();
//コンストラクタ
public SearchSignInAccount_Goto(SystemThread_Goto loginClientThread){
setThread(loginClientThread);
}
//スレッドインスタンス取得
private synchronized void setThread(SystemThread_Goto thread){
threadInstance = thread;
}
public synchronized SystemThread_Goto getThread(){
return threadInstance;
}
//クライアントスレッドインスタンスをObject継承クラス内で管理している本クラスオブジェクトのベクター取得
private static synchronized Vector getClientVector(){
return clientVector;
}
//サインインアカウントスレッドインスタンス(Nクライアント)取得メソッド(同期)
//戻り値は新規に追加したNクライアントもしくは検索されたクライアント
//サインインクライアンントスレッドインスタンスを引数として渡す。Nクライアントの情報を追加もしくは検索。
//サインインクライアントのログインアカウントからNクライアントのスレッドインスタンスを管理しているオブジェクトを取得
public static synchronized SearchSignInAccount_Goto getClientThreadInstance(SystemThread_Goto loginClientThread){
////Nクライアント検索。ログインしたクライアントを追加もしくは検索。
Vector client = SearchSignInAccount_Goto.getClientVector();
//Nクライアント検索処理(未実装)
SearchSignInAccount_Goto clientThreadObject = (SearchSignInAccount_Goto)client.get(0);
if(clientThreadObject == null){
//検索しても見つからない場合は、クライアントスレッドインスタンスの追加
clientThreadObject = new SearchSignInAccount_Goto(loginClientThread);
//Nクライアント追加(未実装)
client.add(clientThreadObject);
}
return clientThreadObject;
}
SystemThread_Goto.java
package net;
import net.SystemLog_Monitor;
import net.SystemThread_Goto;
import net.SearchSignInAccount_Goto;
/* SystemThread javadoc (未実装)*/
//システムスレッドメソッド呼び出し
public class SystemThread_Goto extends Thread {
//サーバ同期オブジェクト
private static final Object serverSyncObj = new Object();
//サインインクライアント同期オブジェクト
private static final Object clientSyncObj = new Object();
//サーバアカウントスレッドインスタンス(同期)1つだけ
private static SystemThread_Goto serverAccount = null;
//ログインユーザースレッドインスタンス管理オブジェクト(非同期)N
private SearchSignInAccount_Goto loginThreadObject = null;
private SystemThread_Goto loginThread = null;
//スレッド処理(スレッドにはコンストラクタ無し)
public void run(){
//モニター出力
SystemLog_Monitor.syslog_moni("[SystemThread_Goto run()]呼出");
//ログインしたアカウントの情報をクラス内に保持。
//サインインアカウントスレッドインスタンス(Nクライアント)取得メソッド(同期)
//戻り値は新規に追加したNクライアントもしくは検索されたNクライアント
//Nクライアント検索。ログインしたNクライアントを追加もしくは検索。
loginThreadObject = new SearchSignInAccount_Goto(this);
loginThread =loginThreadObject.getThread();
//モニター出力
SystemLog_Monitor.syslog_moni("[SystemThread_Goto run()]呼出後");
}
//サーバ処理の同期オブジェクト取得メソッド
public static synchronized Object getServerSyncObject(){
return serverSyncObj;
}
//サインインアカウントクライアント処理の同期オブジェクト取得メソッド
public static synchronized Object getClientSyncObject(){
return clientSyncObj;
}
//サーバアカウントスレッドインスタンス(1つだけ)取得メソッド(同期)
public static synchronized SystemThread_Goto getServerThreadInstance(){
if(serverAccount == null){
serverAccount = new SystemThread_Goto();
}
return serverAccount;
}
public static synchronized void threadjoin(Thread thread) throws InterruptedException {
String logmoni;
logmoni = "new Thread().join();呼出前";
SystemLog_Monitor.syslog_moni(logmoni);
thread.join();
logmoni = "new Thread().join();呼出後";
SystemLog_Monitor.syslog_moni(logmoni);
}
public static synchronized void threadstart(Thread thread) {
String logmoni;
logmoni = "new Thread().start();呼出前";
SystemLog_Monitor.syslog_moni(logmoni);
thread.start();
logmoni = "new Thread().start();呼出後";
SystemLog_Monitor.syslog_moni(logmoni);
}
HardPassword_Goto.java (未実装 シャットダウンしたユーザが機器設定の管理者(オペレーティングシステム管理者))
package net;
//秘密鍵による文字列の暗号化
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import net.SystemLog_Monitor;
import net.HardPassword_Goto;
import net.SystemThread_Goto;
import net.SearchSignInAccount_Goto;
/* HardPassword_Goto javadoc (未実装)*/
//機器設定パスワードシステムオブジェクトクラス
public class HardPassword_Goto extends SearchSignInAccount_Goto {
//オペレーティングシステム管理者秘密鍵
private static final String os_mastar_secletkey = "OS_MASTER_SECLETKEY";
//機器設定パスワード
//OSにサインインしたOS管理者アカウントの情報をクラス内に保持。
private static HardPassword_Goto osPassword = new HardPassword_Goto();
//コンストラクタ
public HardPassword_Goto(){
}
//シャットダウン処理(オペレーティングシステム管理者用)
public synchronized void shutdown(){
//モニター出力
SystemLog_Monitor.syslog_moni("[HardPassword_Goto shutdown()]呼出");
//未実装
//機器設定パスワードの1クライアントでシャットダウンのスレッド処理
//モニター出力
SystemLog_Monitor.syslog_moni("[HardPassword_Goto shutdown()]コンストラクタ呼出後");
}
// 秘密鍵を生成するメソッド
private static synchronized SecretKey generateSecretKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // キーサイズを指定
return keyGen.generateKey();
}
// 文字列を暗号化するメソッド
private static synchronized String encrypt(String data, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
}
// 暗号化された文字列を復号化するメソッド
private static synchronized String decrypt(String encryptedData, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes);
}
//このプログラムでは、次のことが行われています:
//1. **秘密鍵の生成**:AESアルゴリズムを使用して128ビットの秘密鍵を生成します。
//2. **暗号化**:生成した秘密鍵を使って入力文字列を暗号化します。
//3. **復号化**:暗号化された文字列を元の文字列に復号化します。
//このサンプルコードを使用して、秘密鍵を用いた文字列の暗号化と復号化の基本的な仕組みを学べます。必要に応じて、セキュリティ要件やキーマネジメントの方針に合わせて調整してください。
// バイト配列を16進数表記の文字列に変換するメソッド
private static synchronized String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
//AES (Advanced Encryption Standard) を使った例をご紹介します。
public static void main(String[] args){
String originalText = HardPassword_Goto.os_mastar_secletkey;
try{
// 秘密鍵の生成
SecretKey secretKey = generateSecretKey();
// 暗号化
String encryptedText = encrypt(originalText, secretKey);
SystemLog_Monitor.syslog_moni("Encrypted Text: " + encryptedText);
// 復号化
String decryptedText = decrypt(encryptedText, secretKey);
SystemLog_Monitor.syslog_moni("Decrypted Text: " + decryptedText);
// 生成された秘密鍵を表示
SystemLog_Monitor.syslog_moni("Generated Key: " + bytesToHex(secretKey.getEncoded()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
ToStringInstance_Goto.java コンパイルのみ、未実装箇所あり、未テスト。
package net;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Collection;
import java.util.Iterator;
import net.ToStringInstance_Goto;
/* ToStringInstance_Goto javadoc (未実装)*/
public class ToStringInstance_Goto {
private Object privateObj = null;
private String privateString = null;
//ヘッダー(未実装)
private static final StringBuffer printlnHeadderString = new StringBuffer("/*****printlnHeadder*****/\r\n");
//フッター(未実装)
private static final StringBuffer printlnFootterString = new StringBuffer("/*****printlnFootter*****/\r\n");
//ログヘッダー(未実装)
private static final StringBuffer logHeadderString = new StringBuffer("/*****logHeadder*****/\r\n");
//ログフッター(未実装)
private static final StringBuffer logFootterString = new StringBuffer("/*****logFootter*****/\r\n");
//コンストラクタ 文字列変換
public ToStringInstance_Goto(Object obj){
privateObj = obj;
setPrivateString(ToStringInstance_Goto.getToStringInstance_Goto(getPrivateObject()));
}
private synchronized Object getPrivateObject(){
return privateObj;
}
private synchronized String getPrivateString(){
if(privateString == null){
setPrivateString("");
}
return privateString;
}
private synchronized void setPrivateString(String str){
privateString = str;
}
//_Gotoプロジェクト文字列変換メソッド
//デバッグでのNullPointerExceptionを回避するために
//nullは空文字列("")に変換して返却する。
//モニター出力文字列生成メソッド
public static synchronized String getPrintlnToStringInstance(Object obj){
//入力オブジェクトを文字列に変換
StringBuffer strBuf = new StringBuffer(getToStringInstance_Goto(obj));
//入力オブジェクトを文字列に変換後ヘッダーを追加する。
printlnHeadderString.append('\n');
strBuf.insert(0,printlnHeadderString.toString());
//入力オブジェクトを文字列に変換後フッターを追加する。
strBuf.append('\n');
strBuf.append(printlnFootterString.toString());
strBuf.append('\n');
return strBuf.toString();
}
//ログ出力文字列生成メソッド
public static synchronized String getLogToStringInstance(Object obj){
//入力オブジェクトを文字列に変換
StringBuffer strBuf = new StringBuffer(getToStringInstance_Goto(obj));
//入力オブジェクトを文字列に変換後ヘッダーを追加する。
logHeadderString.append('\n');
strBuf.insert(0,logHeadderString.toString());
//入力オブジェクトを文字列に変換後フッターを追加する。
strBuf.append('\n');
strBuf.append(logFootterString.toString());
strBuf.append('\n');
return strBuf.toString();
}
private static synchronized String getToStringInstance_Goto(Object obj){
ToStringInstance_Goto toStringInstance = null;
try{
if(((ToStringInstance_Goto)obj).isToStringInstance_Goto()){
toStringInstance = (ToStringInstance_Goto)obj;
}else{
toStringInstance = new ToStringInstance_Goto(obj);
}
}catch(ClassCastException cast_e){
}
StringBuffer strBuf = new StringBuffer(toStringInstance.toString());
/////////////////////////////
//以下 未実装 文字列変換
/////////////////////////////
//String
try{
String str = (String)obj;
toStringInstance.setPrivateString(str);
return str;
}catch(ClassCastException cast_e){
}
//Logger
try{
Logger log = (Logger)obj;
strBuf.append(log.toString());
strBuf.append('\n');
//未実装 toStringInstance の文字列編集
toStringInstance.setPrivateString(strBuf.toString());
return toStringInstance.toString();
}catch(ClassCastException cast_e){
}
//Level
try{
Level lvl = (Level)obj;
strBuf.append(lvl.toString());
strBuf.append('\n');
//未実装 toStringInstance の文字列編集
toStringInstance.setPrivateString(strBuf.toString());
return toStringInstance.toString();
}catch(ClassCastException cast_e){
}
//Exception
try{
Exception ex = (Exception)obj;
strBuf.append(ex.toString());
strBuf.append('\n');
//未実装 toStringInstance の文字列編集
//String exStr = toStringInstance..getPrivateString();
toStringInstance.setPrivateString(strBuf.toString());
return toStringInstance.toString();
}catch(ClassCastException cast_e){
}
//Collection
try{
Collection col = (Collection)obj;
Iterator it = col.iterator();
while(it.hasNext()){
Object objNext = it.next();
//出力用文字列
strBuf.append(objNext.toString());
strBuf.append('\n');
}
//未実装 toStringInstance の文字列編集
toStringInstance.setPrivateString(strBuf.toString());
return toStringInstance.toString();
}catch(ClassCastException cast_e){
}
/////////////////////////////
//以上 未実装 文字列変換
/////////////////////////////
return toStringInstance.toString();
}
//_Gotoプロジェクト文字列変換メソッド
public synchronized String toString(){
String str = getPrivateString();
if(str == null){
return "null";
}else if("".equals(str)){
return this.toString();
}else{
return str;
}
}
//_Gotoプロジェクト判定メソッド
private synchronized Boolean isToStringInstance_Goto(){
return Boolean.TRUE;
}
}
(Java)Microsoft BingのAI Copilotを使用しています。
Are there any sample programs for synchronization in Java?
copilot answer -> (java synchronized)
スレッドのjoinとは? What is a thread join?
joinメソッドは、現在のスレッドが他のスレッドの完了を待つためのものです。具体的には、あるスレッドがjoinメソッドを呼び出すと、呼び出したスレッドは対象のスレッドが終了するまで待機します。このようにして、メインスレッドなどが他のスレッドの実行終了を待つことができるのです。
public class Main {
public static void main(String[] args) {
//ラムダ式
Thread threadA = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("Thread A: " + i);
}
});
Thread threadB = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("Thread B: " + i);
}
});
threadA.start();
threadB.start();
try {
threadA.join(); // threadAの完了を待つ
threadB.join(); // threadBの完了を待つ
} catch (InterruptedException e) {
e.printStackTrace();
}
// すべてのスレッドが完了してから実行される
System.out.println("All threads have finished.");
}
}
この例では、threadAとthreadBが並列に実行され、joinメソッドを使ってメインスレッドがそれらのスレッドの完了を待機しています。すべてのスレッドが終了した後で、最後のSystem.out.printlnが実行されます。How to use the ReentrantLock class for synchronization.
Javaで同期オブジェクトを使用するサンプルを紹介します。ReentrantLockクラスを使って同期を取る方法 です。
以下にReentrantLockを使用したサンプルコードを示します。
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
この例では、ReentrantLockクラスを使用して、incrementとgetCountメソッドでロックを取得し、処理が完了したらロックを解放しています。これにより、複数のスレッドが安全にカウンタを操作できるようになります。
同期処理を行うには、synchronizedキーワードを使用するのが一般的です。以下にシンプルな例を示します。
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class SynchronizedExample {private int count = 0;
private final Object lock = new Object();
synchronized (lock) {
count++;
}
}
synchronized (lock) {
return count;
}
}
}
この例では、Counterクラスにカウント変数とその操作を定義し、incrementとgetCountメソッドをsynchronizedキーワードで同期しています。このようにすることで、複数のスレッドが同時にメソッドを呼び出しても、データの不整合が生じることを防ぐことができます。
class Counter {
private int count = 0;
// メソッドの同期
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
//ラムダ式
Thread threadA = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread threadB = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
threadA.start();
threadB.start();
try {
threadA.join();
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final count: " + counter.getCount());
}
}