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
- JAVA多线程基础(二)
- java多线程基础(二)
- Java多线程基础(二)
- JAVA多线程基础(二)
- java基础----多线程(二)
- java多线程基础二
- java多线程基础二
- java多线程编程 - 基础篇 (二)
- 黑马程序员 JAVA基础--多线程(二)
- Java基础—多线程(二)
- 黑马程序员--Java基础--多线程(二)
- java基础的核心技术:多线程(二)
- java多线程_基础(二)
- 多线程基础(二)
- Java基础之(三十七)Java多线程编程<二>
- java多线程并发(二)(线程基础)
- 黑马程序员——JAVA基础----多线程(二)
- JAVA进阶学习-多线程基础详解(二)-同步
- js:取消事件的默认行为
- 解决Minimum supported Gradle version is 3.3. Current version is 2.14.1
- Leetcode(9)
- mysql 触发器
- 像素反转
- java多线程基础(二)
- js接口鸭式辨型法实现
- dispatcherServlet详解
- power designer 基础操作
- 微信公众号开发笔记
- ThreadLocal的简单实现
- mysql 数据迁移---使用mysqldump
- 十三、条件化的bean
- Unity中的Path对应各平台中的Path