java多线程基础(二)

来源:互联网 发布:举报网络涉赌 编辑:程序博客网 时间:2024/05/20 17:08

java多线程基础(二)–回顾学习历程,由浅及深,作为个人笔记,也希望帮到需要的人
4、线程间的通信:
上述为多个线程执行同一个任务的情况,多个线程执行不同任务进行协作时,也会面对安全问题。典型的是“生产者-消费者”问题。
(1)由于读或者写的过程中线程切换,导致生产者存入的数据和消费者取出的不一样(数据的原子性)。
(2)生产者反复写入,数据覆盖;消费者反复读取,数据重复。

//生产者Producer,消费者Consumer,产品Prouct//其中产品模型有两个属性:商品名,价格,两者一一对应。生产者负责设置产品属性,消费者负责读取产品属性//不使用synchronized加锁的情况下,消费者读取的产品名和价格可能不一一对应(问题1),同时出现反复读取同一组数据多次(问题2)。class Producer implements Runnable {    private Product p;    private int i = 0;    Producer (Product p) {        this.p = p;    }    @Override    public void run() {        while (true) {            if (i == 0) {                p.setName("肥皂");                p.setPrice(10.0D);            } else {                p.setName("楼房");                p.setPrice(1000000.0D);            }            i = (i+1)%2;        }    }}class Consumer implements Runnable {    private Product p;    Consumer (Product p) {        this.p = p;    }    @Override    public void run() {        while (true) {            System.out.print(p.getName() + " ");            System.out.println(p.getPrice());           }    }}

为了解决这两个问题:
(1)读、写数据本身需要保持独立。例如,写入数据未完成前,不允许读。反之同理。
(2)读、取之前,需要进行线程通信,生产者写完之后才允许读,消费者已经读取才允许写。
所以为两个线程设置同一个同步对象,保证读写不会中断,同时使用wait(),notify()方法完成操作后通知对方

class Producer implements Runnable {    private Product p;    private int i = 0;    Producer (Product p) {        this.p = p;    }    @Override    public void run() {        while (true) {            synchronized (p) {                if (p.isDone()) {                    try {                        p.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                if (i == 0) {                    p.setName("肥皂");                    p.setPrice(10.0D);                } else {                    p.setName("楼房");                    p.setPrice(1000000.0D);                }                i = (i+1)%2;                p.setDone(true);                p.notify();            }        }       }}class Consumer implements Runnable {    private Product p;    Consumer (Product p) {        this.p = p;    }    @Override    public void run() {         while (true) {            synchronized (p) {                if (!p.isDone()) {                    try {                        p.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                System.out.print(p.getName() + " ");                System.out.println(p.getPrice());                p.setDone(false);                p.notify();            }        }    }}

实际使用过程中,往往将同步控制和读取方法让被操作的对象持有,即重构成为Prouduct内的方法。此外,由于多线程可能缓存值,某个线程修改了公共变量值,可能引发不可预知的结果,需要将变量设置为final或者volatile,volatile强制不使用缓存值,而是从主存load到本地线程栈,用完再save回去。

public synchronized void setProduct(String name, Double price) {        if (isDone) {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        this.name = name;        this.price = price;        isDone = true;        notify();    }    public synchronized void printProduct() {        if (!isDone) {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        System.out.println(name + " " + price);        isDone = false;        notify();    }

5、进程的状态:
new,runable,running,blocked,dead
这里写图片描述
调用wait()方法,线程进入等待池(wait blocked pool),调用notify()进入锁定池(lock blocked pool),释放同步锁之后可进入Runnable

0 0
原创粉丝点击