Java多线程同步操作在升级

Java同步问题再升级

消费者与生成者

问题引出

  • 多线程 生产者 消费者操作
    生产者负责信息内容的
  • 每当 生产者 生产完成一项完整的信息之后消费者从生成者取走信息
  • 如果生产者没有 生成完成 消费者等待生成完成 如果消费者没对数据消费 生成者要等待消费后 生成

上代码

class product implements Runnable {
    private Msg msg;

    public product(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            if (x % 2 == 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.setTitle("laowang");
                this.msg.setContent("帅哥");
            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.setTitle("laoliu");
                this.msg.setContent("不是");
            }
        }
    }
}

class consumer implements Runnable {
    private Msg msg;

    public consumer(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.msg.getTitle() + ":" + this.msg.getContent());
        }
    }
}

class Msg {
    private String title;

    private String 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;
    }

}

class tests {
    public static void main(String args[]) {
        Msg msg = new Msg();
        new Thread(new product(msg)).start();
        new Thread(new consumer(msg)).start();
    }

}

结果:

laowang:帅哥
laoliu:不是
laoliu:不是
laoliu:不是
laowang:帅哥
laoliu:帅哥
laowang:帅哥
laowang:帅哥
laowang:帅哥
laowang:不是

发现数据 不同步了

有重复生成 有重复取出的问题


要想解决这个问题 最先解决的得是数据同步

最简单的步骤就是使用synchronized 关键字

msggetset 使用synchronized 关键字来构造

上代码

class product implements Runnable {
    private Msg msg;

    public product(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            if (x % 2 == 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.set("laowang","帅哥");

            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.set("laoliu","不是帅哥");

            }
        }
    }
}

class consumer implements Runnable {
    private Msg msg;

    public consumer(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.msg.get());
        }
    }
}

class Msg {
    private String title;

    private String content;

    public synchronized void set(String title,String content) {
        this.title = title;
        this.content = content;
    }
    public synchronized String get() {
        return this.title + " - " + this.content;
    }
}

class tests {
    public static void main(String args[]) {
        Msg msg = new Msg();
        new Thread(new product(msg)).start();
        new Thread(new consumer(msg)).start();
    }

}

结果

laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥

换一种实现?

等待与唤醒操作

在Object类有三种方法

等待

方法 备注
wait() 死等
wait(long timeout) 设置等待时间
wait(long timeout, int nanos) 设置等待时间

唤醒

方法 备注
notify() 唤醒第一个等待的
notifyAll() 唤醒所有等待的
package com.xiaowang;
//多线程 生产者 消费者操作
//生产者负责信息内容的
//每当 生产者 生产完成一项完整的信息之后消费者从生成者取走信息
//如果生产者没有 生成完成 消费者等待生成完成 如果消费者没对数据消费 生成者要等待消费后 生成

class product implements Runnable {
    private Msg msg;

    public product(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            if (x % 2 == 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.set("laowang", "帅哥");
            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.msg.set("laoliu", "不是帅哥");
            }
        }
    }
}

class consumer implements Runnable {
    private Msg msg;

    public consumer(Msg msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        for (int x = 0; x < 100; x++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.msg.get());
        }
    }
}

class Msg {
    private String title;

    private String content;

    private boolean flag = true;//表示生成或者消费

    //flag = ture 允许生成
    //flag = false 运行消费
    public synchronized void set(String title, String content) {
        if (this.flag == false)
            try {
                super.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        this.title = title;
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.content = content;
        this.flag = false;
        super.notify();
    }

    public synchronized String get() {
        if (this.flag == true) {//生成 还要等待
            try {
                super.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            return this.title + " - " + this.content;
        } finally {
            this.flag = true;
            super.notify();
        }

    }
}

class tests {
    public static void main(String args[]) {
        Msg msg = new Msg();
        new Thread(new product(msg)).start();
        new Thread(new consumer(msg)).start();
    }

}

结果

laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥
laoliu - 不是帅哥
laowang - 帅哥

这么做呢 就是增加了一条判断 判断当前的状态

如果是生成线程 那么执行 生产线程 消费线程 等待 执行完唤醒次线程

如果是消费线程 那么执行消费线程 生成线程 等待 执行完唤醒次线程

原文地址:https://www.cnblogs.com/laowt/p/14546375.html