자바 다 중 스 레 드:생산자 와 소비자 사례
생활 속 의 어떤 것 이 스 레 드 와 관련 이 있 는 지 상상 해 보 세 요.식당 에서 요 리 를 볶 는 것 이 좋 은 예 이다.
먼저 손님 은 음식 을 먹 어야 한다.전 제 는 요리사 가 잘 볶 아야 한 다 는 것 이다.즉,요리사 가 잘 볶 지 않 으 면 손님 은 음식 이 없다 는 것 이다.이때 요리 사 는 하나의 스 레 드 이 고 손님 이 요 리 를 가 져 오 는 것 은 또 다른 스 레 드 이다.
공구.
jdk13,IDEA2019.1.4
지식 점
Thread,Runnable,synchronized,대상 지식(계승,패키지,인터페이스,방법 재 작성),조건 판단 및 스 레 드 에 대한 다른 지식 점
디자인 아이디어
먼저 두 개의 라인 이 있어 야 한다.즉,두 가지 유형 이 있 는데 그것 이 바로 프로듀서(생산자)와 Consumer(소비자)이다.
우 리 는 요리사 와 손님 간 의 상호작용 을 모 의 하기 때문에 메 시 지 를 포장 하 는 유형 이 필요 하 다.
그 다음 에 스 레 드 간 에 데이터 가 혼 란 스 러 운 상황 이 발생 하지 않도록 synchronized 를 사용 하여 스 레 드 동기 화 를 해 야 합 니 다.
구체 적 절차
우선 synchronized 를 사용 하지 않 은 코드 를 보 여 드 리 겠 습 니 다.먼저 효 과 를 보 겠 습 니 다.
public class Message {
private String title;
private String content;
Message(){
};
public Message(String title, String content) {
this.title = title;
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
/*
* Producer
* */
class Producer implements Runnable{
private Message msg=null;
public Producer(Message msg) {
this.msg = msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
if (i%2==0){
this.msg.setTitle(" ?");
try {
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println(e);
}
this.msg.setContent(" !");
}else {
this.msg.setTitle(" ?");
try {
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println(e);
}
this.msg.setContent(" !");
}
}
}
}
/*
* Consumer
* */
class Consumer implements Runnable{
private Message msg=null;
public Consumer(Message msg) {
this.msg = msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
try {
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println(e);
}
System.out.println(this.msg.getTitle()+"--->"+this.msg.getContent());
}
}
}
class TestDemo{
public static void main(String[] args) {
Message msg=new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
}
실행 결과 보기:자세히 보 세 요.데이터 오류 가 발생 했 습 니 다.Title 과 Content 는 일일이 대응 하지 않 았 습 니 다.G.어떻게 하 죠?
어 쩌 겠 어,코드 를 바 꾸 지.
데이터 가 혼 란 스 러 운 이 유 는 생산자 스 레 드 가 아직 생산 되 지 않 았 을 때 소비자 들 이 이미 소 비 했 기 때문이다.그래서 데이터 가 혼 란 스 러 웠 습 니 다.하지만 위 에서 말 했 듯 이 synchronized 를 사용 하여 스 레 드 를 동기 화 시 켜 야 합 니 다.그러나 또 문제 가 생 길 수 있 으 니,우 리 는 이어서 아래 를 내 려 다 보 자.
class TestDemo{
public static void main(String[] args) {
Message msg=new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
}
class Message{
private String title,content;
public synchronized void set(String title,String content){
this.title=title;
this.content=content;
}
public synchronized void get(){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
System.out.println(e);
}
System.out.println(this.title+"-->"+this.content);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
class Producer implements Runnable{
private Message msg=null;
Producer(Message msg){
this.msg=msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
if (i%2==0){
this.msg.set(" ?"," !");
}else {
this.msg.set(" ?"," !");
}
}
}
}
class Consumer implements Runnable{
private Message msg=null;
Consumer(Message msg){
this.msg=msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
this.msg.get();
}
}
}
나 는 또 몇 가지 방법 을 다시 포장 한 후에 운행 할 때 wc,데 이 터 는 오히려 혼 란 스 럽 지 않 았 다.그러나 데 이 터 는 한 무더기 중복 되 었 다.왜 이런 문제 가 생 겼 을 까?마지막 으로 생각해 보 니 이런 문제 가 발생 할 수 있 는 것 은 바로 스 레 드 의 집행 순서 문제 때문이다.우리 가 실현 하고 자 하 는 효 과 는 생산자 스 레 드 가 실 행 된 후에 생산자 스 레 드 를 기다 리 게 한 다음 에 소비자 스 레 드 를 집행 하 게 하고 소비자 스 레 드 가 실 행 된 후에 생산자 스 레 드 를 계속 집행 하 게 하 는 것 이다.나중에 저 는 공식 문 서 를 찾 아 보 았 는데 Object 류 에서 세 가지 방법 이 스 레 드 와 관련 된 것 을 발 견 했 습 니 다.
방법.
묘사 하 다.
public final void wait() throws InterruptedException
스 레 드 대기
public final void notify()
첫 번 째 대기 라인 깨 우기
public final void notifyAll()
내 가 이런 방법 을 보 았 을 때 마음 이 멍 해 졌 다.이것 이 바로 우리 가 원 하 는 방법 이 아 닙 니까?wait()방법 으로 생산자 의 스 레 드 를 기다 리 게 한 다음 에 소비자 스 레 드 를 운행 하고 소비자 스 레 드 가 실 행 된 후에 생산자 스 레 드 를 실행 하 게 합 니 다.그 중에서 우 리 는 true 와 false 로 운행 시작 과 운행 중단 을 표시 합 니 다.
마지막 으로 완성품 의 코드 를 살 펴 보 자.
class TestDemo{
public static void main(String[] args) {
Message msg=new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
}
class Message extends Exception{
private String title,content;
private boolean flag=true;
// true , ,
// false ,
public synchronized void set(String title,String content){
if (this.flag==false){
try {
super.wait();
}catch (InterruptedException e){
System.out.println(e);
}
}
this.title=title;
try {
Thread.sleep(60);
}catch (InterruptedException e){
System.out.println(e);
}
this.content=content;
this.flag=true; // ,
super.notify(); //
}
public synchronized void get(){
if (flag==true) {// ,
try {
super.wait();
}catch (InterruptedException e){
System.out.println(e);
}
}
try {
Thread.sleep(60);
}catch (InterruptedException e){
System.out.println(e);
}
System.out.println(this.title+"-->"+this.content);
this.flag=true;
super.notify();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
class Producer implements Runnable{
private Message msg=null;
Producer(Message msg){
this.msg=msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
if (i%2==0){
this.msg.set(" ?"," !");
}else {
this.msg.set(" ?"," !");
}
}
}
}
class Consumer implements Runnable{
private Message msg=null;
Consumer(Message msg){
this.msg=msg;
}
@Override
public void run() {
for (int i=0;i<=50;i++){
this.msg.get();
}
}
}
운행 결 과 는 붙 이지 않 겠 습 니 다.직접 가서 테스트 해 보 세 요.총결산
이 사례 는 스 레 드 와 대상 지식 을 종합 적 으로 활용 하여 강 한 실제 조작 성 을 가진다.
이 글 은 여기까지 입 니 다.당신 에 게 도움 을 줄 수 있 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 실 수 있 기 를 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.