- 자바 동기화(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월 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 실행
위치:
대한민국
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
String.format 예제 - 자바
- 자바 기준 예제
- 자주 사용하는 예제
1. 기본
- int, long
long value = 123456789;
System.out.println(String.format("%d", value));
System.out.println(String.format("%20d", value));
> 길이지정 결과 출력
- float, double
double value = 12345.6789;
System.out.println(String.format("%f", value));
- 문자열
String value = "ABC";
String value2 = "가나다";
System.out.println(String.format("%s, %s", value, value2));
System.out.println(String.format("%5s, %5s", value, value2));
> 길이지정 결과 출력
- Object
List<Object> list = new ArrayList<>();
list.add("ABC"); list.add(123);
list.add(456.789);
System.out.println(String.format("%s", list));
> toString()이 구현된 형태로 출력
- 배열
Arrays.asList을 이용
System.out.println(String.format("%s", Arrays.asList(new String[] { "123", "가나다" })));
- byte
int value = 65535;
System.out.println(String.format("%x", value));
System.out.println(String.format("%X", value));
System.out.println(String.format("%02X", value));
2. 자리수
- 콤마
double value = 12345.6789;
System.out.println(String.format("%,f", value));
System.out.println(String.format("%,d", (int)value));
> 정수는 d, 소수는 f로 적용
- 소수점 자르기(소수점 표현 지정)
double value = 12345.6789;
System.out.println(String.format("%.6f", value));
> 비는 소수점 자리는 0으로 채움
- 자주 사용하는 예제
1. 기본
- int, long
long value = 123456789;
System.out.println(String.format("%d", value));
System.out.println(String.format("%20d", value));
> 길이지정 결과 출력
- float, double
double value = 12345.6789;
System.out.println(String.format("%f", value));
- 문자열
String value = "ABC";
String value2 = "가나다";
System.out.println(String.format("%s, %s", value, value2));
System.out.println(String.format("%5s, %5s", value, value2));
> 길이지정 결과 출력
- Object
List<Object> list = new ArrayList<>();
list.add("ABC"); list.add(123);
list.add(456.789);
System.out.println(String.format("%s", list));
> toString()이 구현된 형태로 출력
- 배열
Arrays.asList을 이용
System.out.println(String.format("%s", Arrays.asList(new String[] { "123", "가나다" })));
- byte
int value = 65535;
System.out.println(String.format("%x", value));
System.out.println(String.format("%X", value));
System.out.println(String.format("%02X", value));
2. 자리수
- 콤마
double value = 12345.6789;
System.out.println(String.format("%,f", value));
System.out.println(String.format("%,d", (int)value));
> 정수는 d, 소수는 f로 적용
- 소수점 자르기(소수점 표현 지정)
double value = 12345.6789;
System.out.println(String.format("%.6f", value));
> 비는 소수점 자리는 0으로 채움
라벨:
예제,
자바,
Java,
String.format
위치:
대한민국
2016년 11월 12일 토요일
자바 String 기본 예제 - 문자열 다루기
1. 문자열 포함 - contains
System.out.println("ABCD123".contains("CD"));
2. 시작문자열 - startsWith
System.out.println("https://www.google.com".startsWith("https://"));
3. 끝 문자열 - endsWith
System.out.println("image.jpg".endsWith(".jpg"));
4. 비교 - equals, equalsIgnoreCase
- 대소문자 구분
System.out.println("image.jpg".equals("image.jpg"));
- 대소문자 무시
System.out.println("image.jpg".equalsIgnoreCase("IMAGE.jpg"));
5. 문자열 자르기 - substring
- index 부터 자르기
System.out.println("www.google.com".substring(3));
> 결과 : google.com
- 구간 자르기
System.out.println("www.google.com".substring(4, 10));
> 결과 : google
6. 문자열 위치 찾기 - indexOf, lastIndexOf
- 왼쪽 기준에서 위치 찾기
System.out.println("www.google.com".indexOf("google"));
- 오른쪽 기준에서 위치 찾기
System.out.println("www.google.com".lastIndexOf(".com"));
예) 구간 자르기와 함께 쓰기
String value = "www.google.com";
int beginIndex = value.indexOf(".") + 1;
int endIndex = value.lastIndexOf(".");
System.out.println(value.substring(beginIndex, endIndex));
> 결과 : google
> +1을 하는 이유 : 0 w 1 w 2 w 3 . 4 g 5 o 6 o 7 g 8 l 9 e 10 . 11 c 12 o 13 m
7. 정규식 - matches
- 특정 문자가 포함되는 여부 판단
System.out.println("Qwer123".matches(".*[a-z][A-Z].*"));
> 대소문자 포함 여부 확인
8. 문자열 분리(배열) - split
System.out.println(Arrays.asList("www.google.com".split("\\.")));
> 결과 : [www, google, com]
9. 문자열 바꾸기 - replace, replaceAll
- 바꾸기
System.out.println("www.google.com".replace("www", "https://www"));
- 모두 바꾸기
System.out.println("w w w . g o o g l e . c o m".replaceAll(" ", ""));
> 공백 모두 제거
10. 대소문자 변경 - toLowerCase, toUpperCase
- 모두 소문자
System.out.println("www.google.com".toLowerCase());
- 모두 대문자
System.out.println("www.google.com".toUpperCase());
System.out.println("ABCD123".contains("CD"));
2. 시작문자열 - startsWith
System.out.println("https://www.google.com".startsWith("https://"));
3. 끝 문자열 - endsWith
System.out.println("image.jpg".endsWith(".jpg"));
4. 비교 - equals, equalsIgnoreCase
- 대소문자 구분
System.out.println("image.jpg".equals("image.jpg"));
- 대소문자 무시
System.out.println("image.jpg".equalsIgnoreCase("IMAGE.jpg"));
5. 문자열 자르기 - substring
- index 부터 자르기
System.out.println("www.google.com".substring(3));
> 결과 : google.com
- 구간 자르기
System.out.println("www.google.com".substring(4, 10));
> 결과 : google
6. 문자열 위치 찾기 - indexOf, lastIndexOf
- 왼쪽 기준에서 위치 찾기
System.out.println("www.google.com".indexOf("google"));
- 오른쪽 기준에서 위치 찾기
System.out.println("www.google.com".lastIndexOf(".com"));
예) 구간 자르기와 함께 쓰기
String value = "www.google.com";
int beginIndex = value.indexOf(".") + 1;
int endIndex = value.lastIndexOf(".");
System.out.println(value.substring(beginIndex, endIndex));
> 결과 : google
> +1을 하는 이유 : 0 w 1 w 2 w 3 . 4 g 5 o 6 o 7 g 8 l 9 e 10 . 11 c 12 o 13 m
7. 정규식 - matches
- 특정 문자가 포함되는 여부 판단
System.out.println("Qwer123".matches(".*[a-z][A-Z].*"));
> 대소문자 포함 여부 확인
8. 문자열 분리(배열) - split
System.out.println(Arrays.asList("www.google.com".split("\\.")));
> 결과 : [www, google, com]
9. 문자열 바꾸기 - replace, replaceAll
- 바꾸기
System.out.println("www.google.com".replace("www", "https://www"));
- 모두 바꾸기
System.out.println("w w w . g o o g l e . c o m".replaceAll(" ", ""));
> 공백 모두 제거
10. 대소문자 변경 - toLowerCase, toUpperCase
- 모두 소문자
System.out.println("www.google.com".toLowerCase());
- 모두 대문자
System.out.println("www.google.com".toUpperCase());
피드 구독하기:
글 (Atom)