线程的交互
1、基础知识
三个方法:
notify()唤醒 在此 对象监视器上 等待的 单个 线程。
notifyall()::唤醒 在此 对象监视器上 等待的 所有 线程。
wait()::导致当前的线程等待,直到其他线程调用此对象的norify()方法或notifyAll()方法。
关键点是:必须从同步环境内调用wait()、notify()、notifyAll()方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。
例:/**
* 计算输出其他线程锁计算的数据
*/
class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
//启动计算线程
b.start();
//线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者
synchronized (b) {
try {
System.out.println("等待对象b完成计算。。。");
//当前线程A等待
b.wait(); //这里并不是让b去wait,是b的所有者线程wait,但是这个线程的苏醒的条件是b的notify或notifyAll方法的调用而且
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b对象计算的总和是:" + b.total);
}
}
}
/**
* 计算1+2+3 ... +100的和
*
* @author leizhimin 2008-9-15 13:20:49
*/
class ThreadB extends Thread {
int total;
public void run() {
System.out.println("xxxxxxxxxxxxxxxxxrrrrrrrrrrrrrrrrrrrrrx");
synchronized (this) {
System.out.println("xxxxxxxxxxxxxxxxxx");
for (int i = 0; i < 101; i++) {
total += i;
}
//(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
notify();
}
}
}
千万注意:
当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程仍然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁变得可用。
2、norifyAll()
如果需要通知等待某个对象的所有线程,则用notifyAll()让所有在此对象上等待的线程重出等待区,返回到可运行状态。就好比五个人抢一个苹果,当其中一个人强到之后,另外四个人就会休眠状态,然后,当那个人把苹果放下之后notifyAll()会被调用,使得其它四个人都会苏醒,他们四个就会去强那个苹果,当又有人强到苹果之后,wait()方法调用,没有强到苹果的三个人休眠,强到苹果的那个人把苹果放下之后,notifyAll()方法被调用,以此类推,直到所有的人都抢了一次苹果为止。
3、生产者消费者模型
对于此模型,应该明确一下几点:
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
例子:/
public class Test {
public static void main(String[] args) {
Godown godown = new Godown(30);
Consumer c1 = new Consumer(50, godown);
Consumer c2 = new Consumer(20, godown);
Consumer c3 = new Consumer(30, godown);
Producer p1 = new Producer(10, godown);
Producer p2 = new Producer(10, godown);
Producer p3 = new Producer(10, godown);
Producer p4 = new Producer(10, godown);
Producer p5 = new Producer(10, godown);
Producer p6 = new Producer(10, godown);
Producer p7 = new Producer(80, godown);
c1.start();
c2.start();
c3.start();
p1.start();
p2.start();
p3.start();
p4.start();
p5.start();
p6.start();
p7.start();
}
}
* 仓库
*/
class Godown {
public static final int max_size = 100; // 最大库存量
public int curnum; // 当前库存量
Godown() {
}
Godown(int curnum) {
this.curnum = curnum;
}
/**
* 生产指定数量的产品
*/
public synchronized void produce(int neednum) {
// 测试是否需要生产
while (neednum + curnum > max_size) {
System.out.println("要生产的产品数量" + neednum + "超过剩余库存量"
+ (max_size - curnum) + ",暂时不能执行生产任务!");
try {
// 当前的生产线程等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 满足生产条件,则进行生产,这里简单的更改当前库存量
curnum += neednum;
System.out.println("已经生产了" + neednum + "个产品,现仓储量为" + curnum);
// 唤醒在此对象监视器上等待的所有线程
notifyAll();
}
/**
* 消费指定数量的产品
*
* @param neednum
*/
public synchronized void consume(int neednum) {
// 测试是否可消费
while (curnum < neednum) {
try {
// 当前的生产线程等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 满足消费条件,则进行消费,这里简单的更改当前库存量
curnum -= neednum;
System.out.println("已经消费了" + neednum + "个产品,现仓储量为" + curnum);
// 唤醒在此对象监视器上等待的所有线程
notifyAll();
}
}
/**
* 生产者
*/
class Producer extends Thread {
private int neednum; // 生产产品的数量
private Godown godown; // 仓库
Producer(int neednum, Godown godown) {
this.neednum = neednum;
this.godown = godown;
}
public void run() {
// 生产指定数量的产品
godown.produce(neednum);
}
}
/**
* 消费者
*/
class Consumer extends Thread {
private int neednum; // 生产产品的数量
private Godown godown; // 仓库
Consumer(int neednum, Godown godown) {
this.neednum = neednum;
this.godown = godown;
}
public void run() {
// 消费指定数量的产品
godown.consume(neednum);
}
}
分享到:
相关推荐
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
EasyXMS是一个Java编写的用于批量管理Linux服务器的简易系统,如:多线程批量执行命令、多线程批量上传文件等功能. 2种使用模式: 1.交互模式执行动作 2.直接在命令行执行动作 一、运行环境 JDK1.6+ 二、注意事项 1....
/* It is no longer available */ current_location_mcb->is_available = 0; /* We own it */ memory_location = current_location; /* Leave the loop */ break; } } /* If we made...
EasyXMS是一个Java编写的用于批量管理Linux服务器的简易系统,如:多线程批量执行命令、多线程批量上传文件等功能. 2种使用模式: 1.交互模式执行动作 2.直接在命令行执行动作 一、运行环境 JDK1.6+ 二、注意事项 ...
if (op == JOptionPane.NO_OPTION) { System.exit(1); } /* 打印异常栈信息 */ e.printStackTrace(); } } while (ss == null); /* 创建HashSet,用来存放Socket对象 */ hs = new HashSet(); while (true...
线程池里面到底该设置多少个线程IO密集型= 2Ncpu(可以测试后自己控制大小,2Ncpu一般没问题)(常出现于线程中:数据库数据交互,文件...log.debug(“ Load No. {} object,{}”,i,object); log.debug(“ Load
18.1.8 使用SQL风格的交叉连接和隐式内连接 18.1.9 关联级别运行时的检索策略 18.2 投影查询 18.3 报表查询 18.3.1 使用聚集函数 18.3.2 分组查询 18.3.3 优化报表查询的性能 18.4 高级查询技巧 ...
# 这个值(默认8)表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中, # 如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,...
8. services.msc---本地服务设置 9. oobe/msoobe /a----检查XP是否激活 10. notepad--------打开记事本 11. cleanmgr-------垃圾整理 12. net start messenger----开始信使服务 13. compmgmt.msc---计算机管理 ...
18.1.8 使用SQL风格的交叉连接和隐式内连接 18.1.9 关联级别运行时的检索策略 18.2 投影查询 18.3 报表查询 18.3.1 使用聚集函数 18.3.2 分组查询 18.3.3 优化报表查询的性能 18.4 高级查询技巧 ...
18.1.8 使用SQL风格的交叉连接和隐式内连接 18.1.9 关联级别运行时的检索策略 18.2 投影查询 18.3 报表查询 18.3.1 使用聚集函数 18.3.2 分组查询 18.3.3 优化报表查询的性能 18.4 高级查询技巧 ...
18.1.8 使用SQL风格的交叉连接和隐式内连接 18.1.9 关联级别运行时的检索策略 18.2 投影查询 18.3 报表查询 18.3.1 使用聚集函数 18.3.2 分组查询 18.3.3 优化报表查询的性能 18.4 高级查询技巧 ...
x:5:respawn:/usr/bin/X11/xdm -nodaemon #在5级别上运行xdm程序,提供xdm图形方式登录界面,并在退出时重新执行. 六.rc启动脚本 上一节已经提到init进程将启动运行rc脚本,这一节将介绍rc脚本具体的工作。 ...
在其他页面嵌入交互式图表 直接链接到有趣的代码 二进制忍者的全部功能,包括我们的反编译器! 局限性但它确实有一些限制: 不如原生客户端功能丰富 无API 没有插件 性能限制 必须向 V35 提交二进制文件 此 Binary ...
8.关闭资源 主键增长策略: 1.increment:自动增长 select max(id) from table; 找到最大值之后+1赋给要持久化的对象 2.assigned:指派 hibernate不在自动生成主键值,需要你在插入时自己指明 3.hilo:高低值...
8 Android Android Android Android 开发入门 System System System System Requirements Requirements Requirements Requirements The sections below describe the system and software requirements for ...
//_salaryField.enabled = NO; // _textField.placeholder = @"请输入您的银行卡账号"; placeholder 占位符 // _textField.keyboardType = UIKeyboardTypeNumberPad; keyboard键盘 /secure 安全 text 文本 entry ...
§10.13.8 使用ORACLE 诊断工具 126 第三部分 ORACLE应用系统开发优化 128 第11章 诊断与调整工具- 128 §11.1 警告日志文件 128 §11.1.1 警告日志文件管理 128 §11.1.2 参考警告日志文件调整 128 §11.2 后台进程...
6 用户交互 7 加载 Web 页面 8 Web 应用 API 9 通信 10 Web 工作线程 11 Worklets 12 Web 存储 13 HTML 语法 14 XML 语法 15 渲染 16 废弃的特性 17 IANA 注意事项 索引 References Acknowledgments Intellectual ...