- 자바 동기화(synchronized) 기본 예
1. 문제가 되는 코드
- 기본 코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 13312
Thread 1 : 89300
balance : -1000
count total : 102612
> 쓰레드1과 쓰레드2가 동일한 시간에 balance 값이 1000 보다 큰 경우만 -1000을 하면 결과적으로 1000 > 0 > -1000이 되는 문제가 발생한다.
> 루프 카운트도 100000000 / 1000 번을 하는 것이 아닌 것이 확인된다.
2. synchronized 적용
- 기본코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 0
Thread 1 : 100000
balance : 0
count total : 100000
> 쓰레드2는 쓰레드1이 simpleSynchronized 객체를 동기화 하기 때문에 쓰레드1의 작업이 완료되기 전까지 대기 한다.
> synchronized는 동기가 필요한 곳에 적절하게 적용해야 한다.
> 주된 예로 다중쓰레드 환경에서 Map 객체의 put과 remove를 synchronized없이 처리하면 문제가 되는 경우가 있다.
3. 동기화 기본 문법
- 객체 동기화
Object object = new Object();
synchronized (object) {
}
synchronized (this) {
}
> 기본변수(int, long, double 등) 타입은 적용 불가.
- 클래스 단위의 동기화
synchronized (Object.class) {
}
- 메소드 동기화
public synchronized void setObject(Object object) {
}
2019년 3월 8일 금요일
Restful API 예제코드 - HttpURLConnection
1. Restful API - HttpURLConnection
- 기본코드
String urlStr = "https://www.instagram.com/web/search/topsearch/?context=blended&query=java";
URL url = null;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
url = new URL(urlStr);
connection = urlStr.startsWith("https://") ? (HttpsURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("cache-control", "no-cache");
connection.connect();
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
StringBuffer buffer = null;
if (code == HttpURLConnection.HTTP_OK) {
buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String temp = null;
while ((temp = reader.readLine()) != null) {
buffer.append(temp);
}
reader.close();
}
connection.disconnect();
System.out.println(String.format("Response : %d, %s", code, message));
System.out.println("Response DATA : ");
System.out.println(buffer == null ? "NULL " : buffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 결과
Response : 200, OK
Response DATA :
{}
> URL 문자열에서 HTTPS를 판단해서 캐스팅 할 클래스를 선택
> Restful API 사양에 맞는 RequestHeader 설정
> 예제코드에서 사용한 Restful API 주소는 인스타그램 검색 API
- 기본코드
String urlStr = "https://www.instagram.com/web/search/topsearch/?context=blended&query=java";
URL url = null;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
url = new URL(urlStr);
connection = urlStr.startsWith("https://") ? (HttpsURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("cache-control", "no-cache");
connection.connect();
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
StringBuffer buffer = null;
if (code == HttpURLConnection.HTTP_OK) {
buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String temp = null;
while ((temp = reader.readLine()) != null) {
buffer.append(temp);
}
reader.close();
}
connection.disconnect();
System.out.println(String.format("Response : %d, %s", code, message));
System.out.println("Response DATA : ");
System.out.println(buffer == null ? "NULL " : buffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 결과
Response : 200, OK
Response DATA :
{}
> URL 문자열에서 HTTPS를 판단해서 캐스팅 할 클래스를 선택
> Restful API 사양에 맞는 RequestHeader 설정
> 예제코드에서 사용한 Restful API 주소는 인스타그램 검색 API
라벨:
자바,
HttpURLConnection,
Java,
RestAPI,
Restful API
위치:
대한민국
2019년 3월 6일 수요일
칼만필터 예제
1. 기본코드
public class Kalman {
private static final double Q = 0.00001;
private static final double R = 0.001;
private double P = 1;
private double X = 0;
private double K;
public Kalman(double value) {
X = value;
}
// 계산
private void measurementUpdate() {
K = (P + Q) / (P + Q + R);
P = R * (P + Q) / (P + Q + R);
}
// 현재값을 받아 계산된 공식을 적용하고 반환한다
public double update(double measurement) {
measurementUpdate();
X = X + (measurement - X) * K;
return X;
}
}
- 상수 Q와 R의 이해가 필요
- 주 사용처 : 센서(온도, 습도, 자기장, 가속도계), RSSI 시그널 등의 오차 계산
- 칼만필터 위키백과 :
https://ko.wikipedia.org/wiki/%EC%B9%BC%EB%A7%8C_%ED%95%84%ED%84%B0
public class Kalman {
private static final double Q = 0.00001;
private static final double R = 0.001;
private double P = 1;
private double X = 0;
private double K;
public Kalman(double value) {
X = value;
}
// 계산
private void measurementUpdate() {
K = (P + Q) / (P + Q + R);
P = R * (P + Q) / (P + Q + R);
}
// 현재값을 받아 계산된 공식을 적용하고 반환한다
public double update(double measurement) {
measurementUpdate();
X = X + (measurement - X) * K;
return X;
}
}
- 상수 Q와 R의 이해가 필요
- 주 사용처 : 센서(온도, 습도, 자기장, 가속도계), RSSI 시그널 등의 오차 계산
- 칼만필터 위키백과 :
https://ko.wikipedia.org/wiki/%EC%B9%BC%EB%A7%8C_%ED%95%84%ED%84%B0
위치:
대한민국
2019년 3월 5일 화요일
외부 프로세스 실행하기 - 자바
1. 프로세스 실행 - Process
- 메모장 실행 코드
try {
String command = "notepad";
Process process = Runtime.getRuntime().exec(command);
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
- 결과
메모장 프로세스가 호출되면 process.waitFor(); 메소드에서 대기.
메모장 프로세스가 종료되면 process.destroy(); 메소드를 호출하고 종료.
2. 프로세스 출력 가져오기
- 실행코드
try {
String command = "cmd";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "949"));
String temp = null;
while ((temp = reader.readLine()) != null) {
System.out.println(temp);
}
reader.close();
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
- 결과
cmd는 출력 후 종료되는 방식이 아니므로 process.waitFor(); 메소드에서 대기.
keytool 실행 프로세스를 이용해서 테스트 해보면 process.destroy(); 까지 정상적으로 실행됩니다.
라벨:
외부 프로세스 실행,
자바,
Java,
Process,
Runtime 실행
위치:
대한민국
안드로이드 APK 정보 조회 - 서명, AndroidManifast.xml
1. 매니페스트 정보 조회 - AndroidManifast.xml
- 방법
안드로이드 SDK의 포함된 aapt를 통해 확인가능
- 명령어
c:\> aapt.exe dump badging [apk 파일 경로]
예) aapt.exe dump badging app-debug.apk
- 주요 항목 :
package name
versionCode
versionName
적용된 uses-permission
언어별 : application-label
적용된 uses-feature
> 그외 데이터는 출력결과를 직접 확인해서 필요한 데이터를 사용할 것.
2. 서명
- 방법
설치된 JDK의 keytool을 통해 확인 가능
- 명령어
c:\> keytool.exe -printcert -jarfile [apk 파일 경로]
예) keytool.exe -printcert -jarfile app-debug.apk
- 결과 항목 :
소유자
발행자
일련번호
키 생성일
키 만료일
서명 알고리즘 이름
공용키 알고리즘
버전
MD5
SHA1
SHA256
> keytool을 이용해서 키스토어 서명정보와 apk 서명정보를 확인 할 수 있음.
- 방법
안드로이드 SDK의 포함된 aapt를 통해 확인가능
- 명령어
c:\> aapt.exe dump badging [apk 파일 경로]
예) aapt.exe dump badging app-debug.apk
- 주요 항목 :
package name
versionCode
versionName
적용된 uses-permission
언어별 : application-label
적용된 uses-feature
> 그외 데이터는 출력결과를 직접 확인해서 필요한 데이터를 사용할 것.
2. 서명
- 방법
설치된 JDK의 keytool을 통해 확인 가능
- 명령어
c:\> keytool.exe -printcert -jarfile [apk 파일 경로]
예) keytool.exe -printcert -jarfile app-debug.apk
- 결과 항목 :
소유자
발행자
일련번호
키 생성일
키 만료일
서명 알고리즘 이름
공용키 알고리즘
버전
MD5
SHA1
SHA256
> keytool을 이용해서 키스토어 서명정보와 apk 서명정보를 확인 할 수 있음.
위치:
대한민국
크롬 PIP 예제
- 구글 PIP 예제 :
https://developers.google.com/web/updates/2017/09/picture-in-picture
1. HTML 코드
- 샘플영상 출처 :
http://www.ithinknext.com/mydata/board/files/F201308021823010.mp4
- 코드
<html>
<head>
</head>
<body>
<video id="video" src="http://www.ithinknext.com/mydata/board/files/F201308021823010.mp4"></video>
<button id="pipButton">PIP</button>
<script>
// Hide button if Picture-in-Picture is not supported.
pipButton.hidden = !document.pictureInPictureEnabled;
pipButton.addEventListener('click', function() {
// If there is no element in Picture-in-Picture yet, let's request Picture
// In Picture for the video, otherwise leave it.
if (!document.pictureInPictureElement) {
video.requestPictureInPicture()
.catch(error => {
// Video failed to enter Picture-in-Picture mode.
});
} else {
document.exitPictureInPicture()
.catch(error => {
// Video failed to leave Picture-in-Picture mode.
});
}
});
</script>
</body>
</html>
> 결과
https://developers.google.com/web/updates/2017/09/picture-in-picture
1. HTML 코드
- 샘플영상 출처 :
http://www.ithinknext.com/mydata/board/files/F201308021823010.mp4
- 코드
<html>
<head>
</head>
<body>
<video id="video" src="http://www.ithinknext.com/mydata/board/files/F201308021823010.mp4"></video>
<button id="pipButton">PIP</button>
<script>
// Hide button if Picture-in-Picture is not supported.
pipButton.hidden = !document.pictureInPictureEnabled;
pipButton.addEventListener('click', function() {
// If there is no element in Picture-in-Picture yet, let's request Picture
// In Picture for the video, otherwise leave it.
if (!document.pictureInPictureElement) {
video.requestPictureInPicture()
.catch(error => {
// Video failed to enter Picture-in-Picture mode.
});
} else {
document.exitPictureInPicture()
.catch(error => {
// Video failed to leave Picture-in-Picture mode.
});
}
});
</script>
</body>
</html>
> 결과
라벨:
크롬,
Picture-in-Picture,
PIP
위치:
대한민국
Hex.decodeHex - 바이트문자열 변환
- Hex.decodeHex를 통한 byteString을 정수형으로 변환하는 샘플.
1. 기본 예제
String value = "ff";
try {
byte[] bytes = Hex.decodeHex(value);
long result = bytes[0] & 0xff;
System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}
> 결과 : 255
> 0xff 마스크를 적용하지 않으면 -1 결과가 나옴.
> 2의 보수 위키백과 :
https://ko.wikipedia.org/wiki/2%EC%9D%98_%EB%B3%B4%EC%88%98
2. 변환 응용
- long 데이터로 변환 예제
String value = "FF7FFFFFFF";
try {
byte[] bytes = Hex.decodeHex(value);
long result = 0;
for (int i = bytes.length - 1; i >= 0; i--) {
result += (long) (bytes[i] & 0xff) << 8 * i;
}
System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}
1. 기본 예제
String value = "ff";
try {
byte[] bytes = Hex.decodeHex(value);
long result = bytes[0] & 0xff;
System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}
> 결과 : 255
> 0xff 마스크를 적용하지 않으면 -1 결과가 나옴.
> 2의 보수 위키백과 :
https://ko.wikipedia.org/wiki/2%EC%9D%98_%EB%B3%B4%EC%88%98
2. 변환 응용
- long 데이터로 변환 예제
String value = "FF7FFFFFFF";
try {
byte[] bytes = Hex.decodeHex(value);
long result = 0;
for (int i = bytes.length - 1; i >= 0; i--) {
result += (long) (bytes[i] & 0xff) << 8 * i;
}
System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}
> 결과 : 1099511595007
> int형 양수 최대 길이는 7FFFFFFF
피드 구독하기:
글 (Atom)