![๐ Java ๋ก ๋๊ธฐํ๋ฅผ ํด๋ณด์!](/github-blog//assets/img/java-monitor.png)
๐ Java ๋ก ๋๊ธฐํ๋ฅผ ํด๋ณด์!
์ด ๊ธ์์๋ ์ํธ๋ฐฐ์ ๋ฅผ ํตํ ๋๊ธฐํ๋ฅผ ์์๋ณผ ๊ฒ์ด๋ค. ๋๊ธฐํ๋ ํ๋ก์ธ์ค(์ค๋ ๋)๊ฐ ์ํ๋๋ ์์ ์ ์กฐ์ ํ์ฌ ์๋ก๊ฐ ์๊ณ ์๋ ์ ๋ณด๊ฐ ์ผ์นํ๋ ๊ฒ์ธ๋ฐ, ์ฝ๊ฒ ๋งํด ํ๋ก์ธ์ค ๊ฐ ๋ฐ์ดํฐ๊ฐ ์ผ์นํ๋๋ก ํ๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ธ ์ํธ๋ฐฐ์ ๋ ํ๋ก์ธ์ค๋ค์ด ํ์๋ก ํ๋ ์์์ ๋ํด ๋ฐฐํ์ ์ธ ํต์ ๊ถ์ ์๊ตฌํ๋ ๊ฒ์ด๋ค. ์ฝ๊ฒ ๋งํด ํ๋์ ํ๋ก์ธ์ค๊ฐ ๊ณต์ ์์์ ์ฌ์ฉํ ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ๋์ผํ ๊ณต์ ์์์ ์ ๊ทผํ ์ ์๋๋ก ํต์ ํ๋ ๊ฒ์ ๋ปํ๋ค. ์ํธ๋ฐฐ์ ๋ฐฉ๋ฒ์ผ๋ก๋ Mutex, Semaphore ๋ฐฉ์์ด ์ฌ์ฉ๋๋ค. Java ์์๋ Monitor ๋ผ๋ ๋๊ตฌ๋ฅผ ํตํด ๊ฐ์ฒด์ Lock ์ ๊ฑธ์ด ์ํธ๋ฐฐ์ ๋ฅผ ํ ์ ์๋ค. Monitor ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ค ์ ์ด ์ข์์ง ์์๋ณด๊ณ ์ง์ ์ฌ์ฉํด๋ณด์.
๋จผ์ Mutex, Semaphore ๊ฐ๋ ์ ๊ฐ๋จํ๊ฒ ์ดํด๋ณด์.
Mutex
์ฌ๋ฌ ์ค๋ ๋๋ฅผ ์คํํ๋ ํ๊ฒฝ์์ ์์์ ๋ํ ์ ๊ทผ์ ์ ํ์ ๊ฐ์ ํ๊ธฐ ์ํ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ด๋ค. ํน์ง์ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- Boolean ํ์ ์ Lock ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค. ๋ฐ๋ผ์ 1๊ฐ์ ๊ณต์ ์์์ ๋ํ ์ ๊ทผ์ ์ ํํ๋ค.
- ๊ณต์ ์์์ ์ฌ์ฉ ์ค์ธ ์ค๋ ๋๊ฐ ์์ ๋, ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๊ณต์ ์์์ ์ ๊ทผํ๋ค๋ฉด Blocking ํ ๋๊ธฐ ํ๋ก ๋ณด๋ธ๋ค.
- Lock ์ ๊ฑด ์ค๋ ๋๋ง Lock ์ ํด์ ํ ์ ์๋ค.
Semaphore
๋ฉํฐํ๋ก๊ทธ๋๋ฐ ํ๊ฒฝ์์ ๋ค์์ ํ๋ก์ธ์ค๋ ์ค๋ ๋๊ฐ n ๊ฐ์ ๊ณต์ ์์์ ๋ํ ์ ๊ทผ์ ์ ํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉ๋๋ ๋๊ธฐํ ๊ธฐ๋ฒ์ด๋ค.
- ์ธ๋งํฌ์ด ๋ณ์๋ฅผ ํตํด wait, signal ์ ๊ด๋ฆฌํ๋ค. ์ธ๋งํฌ์ด ๋ณ์๋ 0 ์ด์์ ์ ์ํ ๋ณ์๋ฅผ ๊ฐ๋๋ค.
- n ๊ฐ์ ๊ณต์ ์์์ ๋ํ ์ ๊ทผ์ ์ ํํ ์ ์์ผ๋ฉฐ ์ด๋ฅผ ๊ณ์ ์ธ๋งํฌ์ด๋ผ๊ณ ํ๋ค.
- ์ ๊ทผ ๊ฐ๋ฅํ ๊ณต์ ์์์ ์๊ฐ 1๊ฐ์ผ ๋๋ ์ด์ง ์ธ๋งํฌ์ด๋ก ๋ฎคํ ์ค์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
- ํ์ ์ฐ๊ฒฐ๋ ์ค๋ ๋๋ฅผ ๊นจ์ฐ๋ ๋ฐฉ์์ ๋ฐ๋ผ ๊ฐ์ฑ ์ธ๋งํฌ์ด(ํ์ ์ฐ๊ฒฐ๋ ์ค๋ ๋๋ฅผ ๊นจ์ธ ๋ FIFO ์ ์ฑ ), ์ฝ์ฑ ์ธ๋งํฌ์ด(ํ์ ์ฐ๊ฒฐ๋ ์ค๋ ๋๋ฅผ ๊นจ์ธ ๋ ์์๋ฅผ ํน๋ณํ ๋ช ์ํ์ง ์์)๋ก ๊ตฌ๋ถ๋๋ค.
- Lock ์ ๊ฑธ์ง ์์ ์ค๋ ๋๋ Signal ์ ๋ณด๋ด Lock ์ ํด์ ํ ์ ์๋ค.
๋๊ธฐํ ๋ฉ์ปค๋์ฆ
Mutex, Semaphore ๋ ์ํธ๋ฐฐ์ ๋ฅผ ์ํ ๋๊ธฐํ ๊ฐ๋ ์ด๋ค. Framework, Library ์์๋ ์ด ๊ฐ๋ ์ ๋ฐํ์ผ๋ก ๊ตฌํ๋ ์ํธ๋ฐฐ์ ๋๊ตฌ๋ฅผ ์ ๊ณตํ๋ค. ๋ฌผ๋ก C ์ธ์ด ๊ฐ์ ์ธ์ด๋ ์ ๊ณตํ์ง ์๊ธฐ ๋๋ฌธ์ ์ง์ ์ฝ๋๋ฅผ ๊ตฌํํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์๋ค. ๋ํ Semaphore ๋ ์๋ฒฝํ ์ํธ๋ฐฐ์ ๋ฅผ ์ ๊ณตํ๋ค๊ณ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ณด์๊น์ง ํด๋ Monitor ๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ฌ ์ฝ๊ฒ ๋๊ธฐํ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
Monitor
์๊ณ ๊ตฌ์ญ์ ์ง์ผ๋ด๊ธฐ ์ํ ๋ฐฉ๋ฒ์ธ ์ํธ ๋ฐฐ์ ๋ฅผ ํ๋ก๊ทธ๋จ์ผ๋ก ๊ตฌํํ ๊ฒ์ด๋ค. ์ธ๋งํฌ์ด๋ wait & signal ์ฐ์ฐ ์์๋ฅผ ๋ฐ๊ฟ์ ์คํํ๊ฑฐ๋ ๋ ์ค ํ๋๋ผ๋ ์๋ตํ๋ฉด ์ํธ๋ฐฐ์ ๋ฅผ ์๋ฐํ๋ ์ํฉ์ด๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ๋ค. wait & signal ์ฐ์ฐ์ด ํ๋ก๊ทธ๋จ ์ ์ฒด์ ๊ตฌ์ฑ๋์ด ์์ผ๋ฉด ์ธ๋งํฌ์ด์ ์ํฅ์ด ๋ฏธ์น๋ ๊ณณ์ด ์ด๋์ง ํ์ ํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ธ๋งํฌ์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก๊ทธ๋จ์ ๊ตฌํํ๊ธฐ ์ด๋ ต๋ค. ์ด๋ฌํ ๋จ์ ์ ๊ทน๋ณตํ๊ธฐ ์ํด ๋ชจ๋ํฐ๊ฐ ๋ฑ์ฅํ๋ค. ๋ชจ๋ํฐ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ์์ค์์ ์ ๊ณต๋๋ค. ๋ํ์ ์ผ๋ก Java ์์ ์ ๊ณตํ๋ค. ์์ฐจ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๊ณต์ ์์ ํน์ ๊ณต์ ์์ ๊ทธ๋ฃน์ ํ ๋นํ๋ ๋ฐ ์ฌ์ฉ๋๋ค. ๋ชจ๋ํฐ๋ ์ด์ง ์ธ๋งํฌ์ด๋ง ๊ฐ๋ฅํ๋ค. ๋ชจ๋ํฐ๋ฅผ ํตํด ํ๋ก์ธ์ค๊ฐ ์์์ ์ ๊ทผํ๋ ๋ฐฉ์์ ์ด๋ฏธ์ง๋ก ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
๊ณต์ ์์์ ์ ์ ์ค์ธ ํ๋ก์ธ์ค(์ค๋ ๋)๋ Lock ์ ๊ฐ์ง๊ณ ์๋ค. ๊ณต์ ์์์ ์ ์ ์ค์ธ ํ๋ก์ธ์ค(์ค๋ ๋)๊ฐ ์๋ ์ํฉ์์ ๋ค๋ฅธ ํ๋ก์ธ์ค(์ค๋ ๋)๊ฐ ๊ณต์ ์์์ ์ ๊ทผํ๋ ค๊ณ ํ๋ฉด ์ธ๋ถ ๋ชจ๋ํฐ ์ค๋น ํ์์ ์ง์
์ wait
ํ๋ค. Monitor ๋ Semaphore ์ฒ๋ผ signal ์ฐ์ฐ์ ๋ณด๋ด๋ ๊ฒ์ด ์๋๋ผ ์กฐ๊ฑด ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์กฐ๊ฑด์ ๋ํด ๋๊ธฐ ํ์ signal ์ ๋ณด๋ด ์์
์ ์์์ํจ๋ค.
Synchronized
Java ์ synchronized
ํค์๋๋ ์ค๋ ๋ ๋๊ธฐํ๋ฅผ ํ ๋ ์ฌ์ฉํ๋ ๋ํ์ ์ธ ๊ธฐ๋ฒ์ด๋ค. ์๋ฐ์ ๋ชจ๋ ์ธ์คํด์ค๋ Monitor ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ(Object ๋ด๋ถ) Monitor ๋ฅผ ํตํด Thread ๋๊ธฐํ๋ฅผ ์ํํ๋ค. synchronized
ํค์๋๊ฐ ๋ถ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Lock ์ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋ค.
synchronized
๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ฉ์๋ ์์ ํค์๋ ๋ช
์, ์ธ์คํด์ค๋ก ์ฌ์ฉํ๊ธฐ๊ฐ ์๋ค. ๋๊ธฐํ๊ฐ ํ์ํ ๋ฉ์๋ ์์ synchronized
ํค์๋๋ง ๋ถ์ฌ์ฃผ๋ฉด ํธ๋ฆฌํ๊ฒ ๋๊ธฐํ๋ฅผ ์ ์ฉํ ์ ์๋ค. ์ธ์คํด์ค๋ก ์ฌ์ฉํ๋ ค๋ฉด ๋ฉ์๋ ๋ด๋ถ์์ synchronized (๋ฉ์๋) { ๊ตฌํ }
์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
wait, notify
Monitor ์๋ Condition Variable ์ด ์๋๋ฐ ์ด๋ฅผ ํตํด wait()
, notify()
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์๋ค.
Lock ์ ๊ฐ์ง ์ค๋ ๋๊ฐ ๋ค๋ฅธ ์ค๋ ๋์ Lock ์ ๋๊ฒจ์ค ์ดํ์ ๋๊ธฐํด์ผ ํ๋ค๋ฉด wait()
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๊ธฐ ์ค์ธ ์์์ ์ค๋ ๋๋ฅผ ๊นจ์ฐ๋ ค๋ฉด notify()
๋ฅผ ํตํด ๊นจ์ธ ์ ์๋ค. ๋๊ธฐ ์ค์ธ ๋ชจ๋ ์ค๋ ๋๋ฅผ ๊นจ์ฐ๋ ค๋ฉด notifyAll()
์ ํตํด ๊นจ์ธ ์ ์๋๋ฐ, ์ด ๊ฒฝ์ฐ์๋ ํ๋์ ์ค๋ ๋๋ง Lock ์ ํ๋ํ๊ณ ๋๋จธ์ง ์ค๋ ๋๋ ๋ค์ ๋๊ธฐ ์ํ์ ๋ค์ด๊ฐ๋ค.
๋๊ธฐํ๋ฅผ ๊ฒฝํํด ๋ณด์!
๋จผ์ synchronized
๋ฅผ ์ด์ฉํ ๋ฉ์๋ ๋๊ธฐํ์ ๋ธ๋ญ ๋๊ธฐํ๋ฅผ ์ดํด๋ณธ๋ค.
์ด ๋ธ๋ผ์ฐ์ ์ ํน์ง์ ์ดํด๋ณด์.
- ์ต๋ 5๊ฐ์ ํญ์ด ํ์ฑํ๋ ์ ์๋ค.
- 6๊ฐ ์ด์์ ํญ์ด ๋์์ ์ผ์ง๊ฒ ๋๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ๊ฐ์ ์ข ๋ฃ๋๋ค.
- ์๋ก์ด ํญ์ด ์ผ์ง๋ ์๊ฐ์ 0~1์ด๊ฐ ๊ฑธ๋ฆฐ๋ค.
- ์๋ก์ด ํญ์ด ์ผ์ง๋ ๋ก๋ฉ์๊ฐ ๋์์ ํ์ฌ ํ์ฑํ๋ ํญ ์๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ค.
- ๋ธ๋ผ์ฐ์ ๋ก๋ฉ์ด ๋๋ ํ(1์ด ํ) ํญ ์๊ฐ ๊ฐฑ์ ๋๋ค๋ ๋ป์ด๋ค. (4๊ฐ -> ์๋ก์ด ํญ ๋ก๋ฉ(1์ด) -> 1์ด ํ 5๊ฐ)
- ์ฆ, ๋ก๋ฉ ์ค์ ์๋ก์ด ํญ์ด โ์์ง 4๊ฐ๋ฐ์ ํ์ฑํ๋์ง ์์๋ค?โ ๋ผ๊ณ ํ๋จํ๊ณ ์๋ก์ด ํญ์ด ๋ ์ผ์ง ์ ์๋ค๋ ๋ป์ด๋ค.
๋น๋๊ธฐ(๊ฒฐ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์ ์ ๋ค๋ฅธ ์์ ์ด ์ด๋ฃจ์ด์ง๋ ๊ฒ)๋ก ์ฒ๋ฆฌ๊ฐ ๋๋ค๋ฉด ์๋ก์ด ํญ์ด ์ถ๊ฐ๋๊ธฐ ์ํด ๋ก๋ฉ ์ค์ธ ์ํฉ์์ ๋ ๋ค๋ฅธ ํญ์ด ์ถ๊ฐ๋๋ ๊ฒ์ ์๋ํ๋ค๋ฉด ๊ณง์ด์ด ๊ฐ์ ์ข ๋ฃ๊ฐ ๋๋ ์ํฉ์ด ๋ฐ์ํ๋ ๊ฒ์ ์ ์ ์๋ค. ๊ทธ ๋๋ฌธ์ ์๋ก์ด ํญ์ด ์ถ๊ฐ๋๋ ์ํฉ์๋ ๋ค๋ฅธ ํญ์ด ์ถ๊ฐ๋๋ ์์ ์ ๋ง์ ํ์๊ฐ ์๋ค.
์ธ ๊ฐ์ ํด๋์ค๋ฅผ ์ค๋นํ๋ค.
๋๊ธฐํ, ๋น๋๊ธฐํ ์ํ์ ๋ฐ๋ผ ์ค๋ ๋๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง ์์๋ณด๋ ์ค์ต์ด๋ฏ๋ก ์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ์ฌ์ฉํ๋ฉด ๋๋ค.
public class Computer {
public static void main(String[] args) {
final WebBrowser webBrowser = new WebBrowser(5);
final Thread threadA = new Thread(new WebSite("Google", webBrowser));
final Thread threadB = new Thread(new WebSite("Naver", webBrowser));
final Thread threadC = new Thread(new WebSite("Daum", webBrowser));
threadA.start();
threadB.start();
threadC.start();
}
}
public class WebSite implements Runnable {
private final String webSiteName;
private final WebBrowser webBrowser;
public WebSite(final String webSiteName, final WebBrowser webBrowser) {
this.webSiteName = webSiteName;
this.webBrowser = webBrowser;
}
@Override
public void run() {
// ๋ฉ์๋ ๋ธ๋ญ ๋๊ธฐํ
synchronized (this) {
while (webBrowser.hasSpace()) {
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
webBrowser.createNewTab(webSiteName);
}
}
}
}
public class WebBrowser {
private static final String SPACE = " ";
private final List<String> webSiteNames = new ArrayList<>();
private final int maxWebCount;
public WebBrowser(final int maxWebCount) {
this.maxWebCount = maxWebCount;
}
// ๋ฉ์๋ ๋๊ธฐํ
public synchronized void createNewTab(final String webSiteName) {
try {
if (full()) {
return;
}
System.out.println(webSiteName + " ์ฌ์ดํธ๊ฐ ์ผ์ง๋ ์ค์
๋๋ค...");
Thread.sleep(new Random().nextInt(1000));
webSiteNames.add(webSiteName);
showRunningBrowser();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void showRunningBrowser() {
if (webSiteNames.size() > maxWebCount) {
throw new UnsupportedOperationException("ํ์ฌ ๋ธ๋ผ์ฐ์ ํญ์ด 6๊ฐ ์ด์ ํ์ฑํ ๋์ด ๊ฐ์ ์ข
๋ฃํฉ๋๋ค...");
}
System.out.println("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
System.out.println("โ โ Wilder Web Browser - โก x โ");
System.out.println("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
StringBuilder browserNameLine = new StringBuilder();
StringBuilder browserUnderLine = new StringBuilder();
if (webSiteNames.size() > 0) {
browserNameLine.append("โ");
browserUnderLine.append("โ");
}
for (int i = 0; i < webSiteNames.size(); i++) {
browserNameLine.append(generateWebSiteName(webSiteNames.get(i)))
.append(i + 1)
.append(" โ");
browserUnderLine.append("โโโโโโโโโโโโโโโโ");
}
System.out.println(browserNameLine);
System.out.println(browserUnderLine);
}
private String generateWebSiteName(final String name) {
StringBuilder builder = new StringBuilder();
if (name.length() > 11) {
return name.substring(0, 11);
}
int space = 11 - name.length();
int interval = space / 2;
builder.append(SPACE.repeat(interval))
.append(name)
.append(SPACE.repeat(11 - interval - name.length()));
return builder.toString();
}
public boolean hasSpace() {
return webSiteNames.size() < maxWebCount;
}
private boolean full() {
return !hasSpace();
}
}
Computer ํด๋์ค์ main ๋ฉ์๋๋ฅผ ์คํํด ๋ณธ๋ค. ์์ ์์๋ synchronized
ํค์๋๋ฅผ ํตํด ๊ฐ๋จํ๊ฒ ๋ชจ๋ํฐ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค. ํด๋น ์ฝ๋๋ฅผ ์คํํด ๋ณด๋ฉด ์๋์ ๋น์ทํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
์ฌ๊ธฐ์ ํต์ฌ์ ์ฌ๋ฌ ์ค๋ ๋์์ ์๋ก์ด ํญ์ ์ถ๊ฐํ์ง๋ง, ํญ์ด 5๊ฐ๋ฅผ ์ด๊ณผํ์ฌ ์์ฑ๋์ง ์๋๋ค๋ ๊ฒ์ ์ ์ ์๋ค. synchonized
ํค์๋๋ฅผ ์ ๊ฑฐํ๊ณ ๋ค์ ์คํํด ๋ณด์. WebBrowser
ํด๋์ค์ createNewTab
๋ฉ์๋์ WebSite
์ run
๋ฉ์๋์ synchronized
๋ถ๋ถ์ ์ ๊ฑฐํ๋ค.
public void createNewTab(final String webSiteName) {
try {
if (full()) {
return;
}
System.out.println(webSiteName + " ์ฌ์ดํธ๊ฐ ์ผ์ง๋ ์ค์
๋๋ค...");
Thread.sleep(new Random().nextInt(1000));
webSiteNames.add(webSiteName);
showRunningBrowser();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (webBrowser.hasSpace()) {
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
webBrowser.createNewTab(webSiteName);
}
}
์์ ๊ฐ์ด ๋ณ๊ฒฝํ ํ ์คํํด ๋ณด๋ฉด ์ค๋ ๋๊ฐ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋๋ฉด์ 6๊ฐ ์ด์์ ํญ์ด ํ์ฑํ๋๋ฉฐ ์์ธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์์ ์ค์ต์ผ๋ก ๋๊ธฐํ๊ฐ ์ด๋ป๊ฒ ์งํ๋๋์ง ์์๋ณด์๋ค. ๋ค์์ wait(), notify() ๋ฅผ ์ด์ฉํ ๋๊ธฐํ๋ฅผ ํด๋ณด์.
์กฐ๊ฑด ๋ณ์๋ฅผ ํตํ ๋ชจ๋ํฐ ๋๊ธฐํ
wait
, notify
๋ฅผ ์ฌ์ฉํ๋ค. ์ด์ ์ ์ฌ์ฉํ ์ฝ๋์ ๋น์ทํ์ง๋ง, ์ผ๋ถ ๋ณ๊ฒฝ ์ ์ด ์๋ค.
- 3์ด๋ง๋ค ๊ฐ์ฅ ๋จผ์ ์ผ์ง ์น ์ฌ์ดํธ๊ฐ ๊บผ์ง๋ค.
- ์น ์ฌ์ดํธ๊ฐ ๊บผ์ง๋ฉด ๋๊ธฐ ์ค์ด๋ ์น ์ฌ์ดํธ๊ฐ ์ผ์ง๋ค.
- ์น ์ฌ์ดํธ๊ฐ 5๊ฐ๊ฐ ์ผ์ง๋ฉด ์น ์ฌ์ดํธ๋ ๋๊ธฐ ์ํ์ ๋ค์ด๊ฐ๋ค.
- ์น ์ฌ์ดํธ๊ฐ 5๊ฐ ์ดํ๊ฐ ์ผ์ ธ ์์ผ๋ฉด ๋๊ธฐ ์ค์ด๋ ์น ์ฌ์ดํธ๊ฐ ์ผ์ง๋ค.
์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ์ค์ตํด ๋ณด์.
public class Computer {
public static void main(String[] args) {
final WebBrowser webBrowser = new WebBrowser(5);
final Thread threadA = new Thread(new WebSite("Google", webBrowser));
final Thread threadB = new Thread(new WebSite("Naver", webBrowser));
final Thread threadC = new Thread(new WebSite("Daum", webBrowser));
final Thread closer = new Thread(new WebSiteCloser(webBrowser));
closer.start();
threadA.start();
threadB.start();
threadC.start();
}
}
public class WebSite implements Runnable {
private final String webSiteName;
private final WebBrowser webBrowser;
public WebSite(final String webSiteName, final WebBrowser webBrowser) {
this.webSiteName = webSiteName;
this.webBrowser = webBrowser;
}
@Override
public void run() {
synchronized (this) {
while (true) {
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
webBrowser.createNewTab(webSiteName);
}
}
}
}
public class WebBrowser {
private static final String SPACE = " ";
private final List<String> webSiteNames = new ArrayList<>();
private final List<Integer> webSiteIndexes = new ArrayList<>();
private final int maxWebCount;
private int webSiteIndex = 0;
public WebBrowser(final int maxWebCount) {
this.maxWebCount = maxWebCount;
}
public synchronized void createNewTab(final String webSiteName) {
try {
if (full()) {
wait();
}
System.out.println(webSiteName + " ์ฌ์ดํธ๊ฐ ์ผ์ง๋ ์ค์
๋๋ค...");
Thread.sleep(new Random().nextInt(1000));
webSiteNames.add(webSiteName);
webSiteIndexes.add(++webSiteIndex);
showRunningBrowser();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void showRunningBrowser() {
if (webSiteNames.size() > maxWebCount) {
throw new UnsupportedOperationException("ํ์ฌ ๋ธ๋ผ์ฐ์ ํญ์ด 6๊ฐ ์ด์ ํ์ฑํ ๋์ด ๊ฐ์ ์ข
๋ฃํฉ๋๋ค...");
}
System.out.println("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
System.out.println("โ โ Wilder Web Browser - โก x โ");
System.out.println("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
StringBuilder browserNameLine = new StringBuilder();
StringBuilder browserUnderLine = new StringBuilder();
if (webSiteNames.size() > 0) {
browserNameLine.append("โ");
browserUnderLine.append("โ");
}
for (int i = 0; i < webSiteNames.size(); i++) {
browserNameLine.append(generateWebSiteName(webSiteNames.get(i)))
.append(generateWebSiteIndex(webSiteIndexes.get(i)))
.append(" โ");
browserUnderLine.append("โโโโโโโโโโโโโโโโ");
}
System.out.println(browserNameLine);
System.out.println(browserUnderLine);
}
private String generateWebSiteName(final String name) {
StringBuilder builder = new StringBuilder();
if (name.length() > 11) {
return name.substring(0, 11);
}
int space = 11 - name.length();
int interval = space / 2;
builder.append(SPACE.repeat(interval))
.append(name)
.append(SPACE.repeat(11 - interval - name.length()));
return builder.toString();
}
private String generateWebSiteIndex(final int index) {
if (index < 10) {
return "00" + index;
}
if (index < 100) {
return "0" + index;
}
return "" + index;
}
public boolean isNotEmpty() {
return webSiteNames.size() != 0;
}
public boolean hasSpace() {
return webSiteNames.size() < maxWebCount;
}
public boolean full() {
return !hasSpace();
}
public synchronized void removeAndNotify() {
if (isNotEmpty()) {
System.out.println(webSiteNames.get(0) + " ์ฌ์ดํธ๊ฐ ์ข
๋ฃ๋ฉ๋๋ค.");
webSiteNames.remove(0);
webSiteIndexes.remove(0);
showRunningBrowser();
notify();
}
}
}
public class WebSiteCloser implements Runnable {
private final WebBrowser webBrowser;
public WebSiteCloser(WebBrowser webBrowser) {
this.webBrowser = webBrowser;
}
@Override
public void run() {
try {
while (true) {
Thread.sleep(3000);
webBrowser.removeAndNotify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5๊ฐ๋ฅผ ๋์ง ์๋ ์ ์์ ์๋ก์ด ํญ์ด ๋น์๋ฆฌ๊ฐ ์๊ธธ ๋๋ง๋ค ์ถ๊ฐ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋ ๊ฒ ์กฐ๊ฑด ๋ณ์๋ฅผ ์ด์ฉํ์ฌ ๋๊ธฐํ๋ฅผ ํด๋ณด๋ ๊ฒฝํ๊น์ง ํด๋ดค๋ค. ์ ์ ํ ์์๋ ์๋ ์ ์์ง๋ง, ์ด ๊ธ์ ํต์ฌ์ ์ด๋ป๊ฒ, ์ด๋ค ๋ฐฉ์์ผ๋ก Java ์์ ๋๊ธฐํ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋์ง๋ฅผ ์์๋ณด๋ ์๊ฐ์ด์๋ค.
๊ฒฐ๋ก
Java ์์ ์ ๊ณต๋๋ ๋ชจ๋ํฐ๋ ์์ฝ๊ฒ ์ํธ๋ฐฐ์ ๋ฅผ ํ ์ ์๋๋ก ํด์ค๋ค. ๋๋ถ๋ถ ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ์ค๋ ๋ ์ธ์ดํ ํ์ง ์์ ํ๊ฒฝ์์๋ ๋๊ธฐํ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ์๋ฅผ ๋ค๋ฉด ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋ค. ์ด๋ ์ฑ๊ธํค ํจํค(๋จ ํ๋์ ์ธ์คํด์ค๋ง ๋ง๋๋ ํจํด)์ ์ฌ์ฉํ๋ค๋ฉด ์ฒ์ ์ฑ๊ธํค์ ์์ฑํ ๋ ์ค๋ ๋ ์ธ์ดํ ํ์ง ์๋ค. ์ด ๊ฒฝ์ฐ์ ๋๊ธฐํ๊ฐ ํ์ํ๋ค. ์ด์ฒ๋ผ ๋๊ธฐํ๊ฐ ํ์ํ ์ํฉ์ด ์ข ์ข ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ด๋ ๋ชจ๋ํฐ๋ฅผ ํ์ฉํ์ฌ ์ฝ๊ฒ ๋๊ธฐํ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ฐธ๊ณ
- Synchronized Method Docs
- Monitor Docs
- ์ด์์ฒด์ - ์ํธ๋ฐฐ์ ์ ๋๊ธฐํ(๋ฎคํ ์ค,TAS,์ธ๋งํฌ์ด,๋ชจ๋ํฐ)
- JAVA] WAIT()์ NOTIFY()