Javaの学習の概要:29

スレッドプロデューサーとコンシューマーケースの間の古典的な操作ケース

基本的なプログラムモデル:

package Project.Study.Multithreading;

class Message{
    private String title;   //保存信息的标题
    private String content; //保存信息的内容
    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }
}
class Producer implements Runnable{		//定义生产者
    private Message msg=null;
    public Producer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run(){
        for (int x=0;x<50;x++){				//生产50次数据
            if(x%2==0){
                this.msg.setTitle("小关");	//定义title属性
                try {
                    Thread.sleep(100);		//延迟操作
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                this.msg.setContent("学习Java");//设置content属性
            }else{
                this.msg.setTitle("小梁");		//设置title属性
                try {
                    Thread.sleep(100);			//延迟操作
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                this.msg.setContent("学习python");//设置content属性
            }
        }
    }
}
class Consumer implements Runnable{
    private Message msg;
    public Consumer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run(){
        for(int x=0;x<50;x++){
            try{
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(this.msg.getTitle()+"-->"+this.msg.getContent());
        }
    }
}
public class Test10 {
    public static void main(String []args){
        Message msg=new Message();
        new Thread(new Producer(msg)).start();
        new Thread(new Consumer(msg)).start();
    }
}
//结果:
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//(...)

もともとプログラムの予想される出力は、Xiaoguan-> Learning Java、Xiaoliang-> Learning pythonです
が、明らかに問題があり、設定されたデータがずれており、データが繰り返し取り出され、繰り返し設定されています。

データの乱れの問題を解決する

データの不整合は完全に非同期操作によるものであるため、同期処理を使用する必要があります。
例:データの乱れの問題を解決するために同期に参加する

package Project.Study.Multithreading;

class Message2{
    private String title;   //保存信息的标题
    private String content; //保存信息的内容
    public synchronized void set(String title,String content){
        this.title=title;
        try{
            Thread.sleep(100);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        this.content=content;
    }
    public synchronized void get(){
        try{
            Thread.sleep(100);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println(this.title+"-->"+this.content);
    }
}
class Producer2 implements Runnable{
    private Message2 meg=null;
    public Producer2(Message2 msg){
        this.meg=msg;
    }
    @Override
    public void run(){
        for(int x=0;x<20;x++){
            if(x%2==0){
                this.meg.set("小关","学习Java");
            }else{
                this.meg.set("小梁","学习Python");
            }
        }
    }
}
class Consumer2 implements Runnable{
    private Message2 msg=null;
    public Consumer2(Message2 msg){
        this.msg=msg;
    }
    @Override
    public void run(){
        for (int x=0;x<20;x++){
            this.msg.get();
        }
    }
}
public class Test11 {
    public static void main(String []args)throws Exception{
        Message2 msg=new Message2();
        new Thread(new Producer2(msg)).start();
        new Thread(new Consumer2(msg)).start();
    }
}
//结果:
//小梁-->学习Python
//小梁-->学习Python
//小梁-->学习Python
//小梁-->学习Python
//(...)

上記の手順により、データの不整合の問題は解決されますが、削除と設定の繰り返しの問題は依然として残っています。

データの重複を解決する

マルチスレッドのオブジェクトクラスのサポート

番号。 方法 タイプ 説明文
1 public final void wait()は、InterruptedExceptionをスローします 普通の スレッド待機中
2 public final void notify() 普通の 最初の待機中のスレッドを起こす
public final void notifyAll() 普通の 待機中のすべてのスレッドを起こす

一般に、待機中のスレッドはすべて順番に配置されます。
notify()メソッドを使用すると、最初の待機中のスレッドが起こされ
、notifyAll()メソッドを使用すると、すべての待機中のスレッドが起こされます。最も優先順位の高いスレッドが最初に実行されます。

例:

package Project.Study.Multithreading;

class Message3{
    private String title;
    private String content;
    private boolean flag=true;
    //flag==true:表示可以生产,但是不能拿走
    //flag==false:表示可以取走,但是不能生产
    public synchronized void set(String title,String content){
        if(this.flag==false){
            try {
                super.wait();                   //等待
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        this.title=title;
        try {
            Thread.sleep(100);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        this.content=content;
        this.flag=false;                        //已经生产完成,修改标志位
        super.notify();                         //唤醒等待线程
    }
    public synchronized void get(){
        if (this.flag==true){                   //未生产,不能取走
            try {               
                super.wait();                   //等待
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(100);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println(this.title+"-->"+this.content);
        this.flag=true;                         //已经取走了,可以继续生产
        super.notify();                         //唤醒等待线程
    }
}
class Producer3 implements Runnable{
    private Message3 meg;
    public Producer3(Message3 msg){
        this.meg=msg;
    }
    @Override
    public void run(){
        for(int x=0;x<10;x++){
            if(x%2==0){
                this.meg.set("小关","学习Java");
            }else{
                this.meg.set("小梁","学习Python");
            }
        }
    }
}
class Consumer3 implements Runnable{
    private Message3 msg;
    public Consumer3(Message3 msg){
        this.msg=msg;
    }
    @Override
    public void run(){
        for (int x=0;x<10;x++){
            this.msg.get();
        }
    }
}

public class Test12 {
    public static void main(String []args){
        Message3 msg=new Message3();
        new Thread(new Producer3(msg)).start();
        new Thread(new Consumer3(msg)).start();
    }
}
//结果:
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python

上記の手順は、データの不整合、繰り返しのデータ削除、繰り返しの設定の問題を解決します。

ヒント:
sleep()とwait()の違い:
1.sleep()はThreadクラスによって定義された静的メソッドです。つまり、スレッドはスリープし、他のスレッドに実行機会を与えますが、監視状態は維持され、自動的に再開されます
。2.wait( )Objectクラスによって定義されたメソッドです。つまり、スレッドは、notify()またはnotifyAll()が実行されるまで待機します。

发布了49 篇原创文章 · 获赞 25 · 访问量 1519

おすすめ

転載: blog.csdn.net/weixin_45784666/article/details/105067987