Java 스레드 간 통신 방식 상세 정보
① 동기화
여기서 말하는 동기화는 여러 개의 라인이synchronized 키워드를 통해 라인 간의 통신을 실현하는 것을 가리킨다.
참조 예:
public class MyObject {
synchronized public void methodA() {
//do something....
}
synchronized public void methodB() {
//do some other thing
}
}
public class ThreadA extends Thread {
private MyObject object;
//
@Override
public void run() {
super.run();
object.methodA();
}
}
public class ThreadB extends Thread {
private MyObject object;
//
@Override
public void run() {
super.run();
object.methodB();
}
}
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
// A B :object
ThreadA a = new ThreadA(object);
ThreadB b = new ThreadB(object);
a.start();
b.start();
}
}
스레드 A와 스레드 B는 같은 MyObject 클래스의 대상인object를 가지고 있기 때문에 이 두 스레드는 서로 다른 방법을 호출해야 하지만, 그것들은 동시에 실행된다. 예를 들어 스레드 B는 스레드 A가methodA() 방법을 실행한 후에methodB() 방법을 실행할 수 있다.이렇게 하면 스레드 A와 스레드 B가 통신을 실현할 수 있다.이런 방식은 본질적으로'공유 메모리'식의 통신이다.여러 개의 루틴은 같은 공유 변수에 접근해야 하며, 자물쇠를 얻은 사람이 실행할 수 있다.
② while 폴링 방식
코드는 다음과 같습니다.
import java.util.ArrayList;
import java.util.List;
public class MyList {
private List<String> list = new ArrayList<String>();
public void add() {
list.add("elements");
}
public int size() {
return list.size();
}
}
import mylist.MyList;
public class ThreadA extends Thread {
private MyList list;
public ThreadA(MyList list) {
super();
this.list = list;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
list.add();
System.out.println(" " + (i + 1) + " ");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import mylist.MyList;
public class ThreadB extends Thread {
private MyList list;
public ThreadB(MyList list) {
super();
this.list = list;
}
@Override
public void run() {
try {
while (true) {
if (list.size() == 5) {
System.out.println("==5, b ");
throw new InterruptedException();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import mylist.MyList;
import extthread.ThreadA;
import extthread.ThreadB;
public class Test {
public static void main(String[] args) {
MyList service = new MyList();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
이런 방식으로 스레드 A는 끊임없이 조건을 바꾸고, 스레드ThreadB는 끊임없이 while 문장을 통해 이 조건(list.size()=5)의 성립 여부를 검사하여 스레드 간의 통신을 실현했다.그러나 이런 방식은 CPU 자원을 낭비할 수 있다.자원을 낭비하는 이유는 JVM 스케줄러가 CPU를 스레드 B에 넘겨 실행할 때 유용한 작업은 하지 않고 조건이 성립되었는지 끊임없이 테스트하기 때문이다.마치 현실에서 누군가가 핸드폰 화면에 전화가 왔는지 안 왔는지 계속 보고 있는 것과 같다. 다른 일을 하고 있는데 전화가 왔을 때 벨을 울리면 전화가 왔음을 알리는 것이다.루틴에 대한 윤문의 영향은 참고할 수 있습니다Java의 스레드가 다운사이클을 수행하면 어떤 결과가 발생합니까 ③ wait/notify 메커니즘
코드는 다음과 같습니다.
import java.util.ArrayList;
import java.util.List;
public class MyList {
private static List<String> list = new ArrayList<String>();
public static void add() {
list.add("anyString");
}
public static int size() {
return list.size();
}
}
public class ThreadA extends Thread {
private Object lock;
public ThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized (lock) {
if (MyList.size() != 5) {
System.out.println("wait begin "
+ System.currentTimeMillis());
lock.wait();
System.out.println("wait end "
+ System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadB extends Thread {
private Object lock;
public ThreadB(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
MyList.add();
if (MyList.size() == 5) {
lock.notify();
System.out.println(" ");
}
System.out.println(" " + (i + 1) + " !");
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
Object lock = new Object();
ThreadA a = new ThreadA(lock);
a.start();
Thread.sleep(50);
ThreadB b = new ThreadB(lock);
b.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
스레드 A는 조건이 충족될 때(list.size () = 5) 작업을 수행합니다.스레드 B는list에 요소를 추가하여list의size를 변경합니다.A, B는 어떻게 통신합니까?즉, 라인 A가list를 어떻게 알았는지.사이즈 () 벌써 5인데?
Object 클래스의wait () 및 notify () 메서드가 사용됩니다.
조건이 충족되지 않으면 (list.size ()!=5), 스레드 A 호출wait()는 CPU를 포기하고 차단 상태로 들어갑니다. ---②while 폴링처럼 CPU를 사용하지 않음
조건이 충족되면 스레드 B는 notify () 알림 스레드 A를 호출합니다. 알림 스레드 A란 스레드 A를 깨우고 실행 가능한 상태로 만드는 것입니다.
이런 방식의 장점 중 하나는 CPU의 이용률이 높아졌다는 것이다.
그러나 단점도 있다. 예를 들어 스레드 B가 먼저 실행되고 한꺼번에 5개의 요소를 추가하고 notify () 를 호출하여 알림을 보냈는데 이때 스레드 A가 실행되었다.스레드 A가wait () 를 실행하고 호출할 때, 영원히 깨어날 수 없습니다.왜냐하면 라인 B가 이미 통지를 보냈기 때문에 이후에 더 이상 통지를 보내지 않을 것이다.이것은 알림이 너무 이르면 프로그램의 실행 논리를 혼란시킬 수 있다는 것을 설명한다.
이상은 본고의 전체 내용입니다. 여러분이 자바 프로그래밍을 배우는 데 도움이 되기를 바랍니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.