chidaodezhongsheng
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(2)
给我留言
查看公开留言
查看私人留言
随笔档案
2012年1月 (1)
2010年10月 (1)
文章档案
2010年12月 (7)
2010年11月 (6)
2010年10月 (24)
搜索
最新评论
1. re: Http参数传递时的乱码过滤器[未登录]
是是是是是是
--啊啊
2. re: Servlet配置到Web.xml中
配置好了 它整体的流程是什么啊?
--Tovep
3. re: JDBC基本操作
期待...
--Tovep
4. re: 再写银行排队
LZ 写的不错 啊!!!
--Tovep
5. re: 生产消费问题
臭小子 居然FZZT
--Tovep
阅读排行榜
1. 无题(188)
2. 很久没更新了,真的太久了(170)
评论排行榜
1. 很久没更新了,真的太久了(0)
2. 无题(0)
Powered by:
博客园
模板提供:
沪江博客
BlogJava
|
首页
|
发新随笔
|
发新文章
|
联系
|
聚合
|
管理
生产消费问题
java中一个比较著名的问题就是生产消费问题,就是一边生产出产品,另一边就消费掉刚刚生产出来的产品,这里面需要用到线程同步和信号量的问题。
线程同步就是实现线程安全的一种手段,是处理资源共享问题的必须手段。假如多个线程去共享同一个资源,肯定会发生我们意想不到的问题,使得线程并不安全,例如重复取出相同资源。
而使用信号量是控制各个线程之间调用顺序的方法,通过信号量让线程不断休息和唤醒,这样来实现我们想要的功能。
下面看一个不加线程同步和信号量的程序:
class
Person
{
private
String name ;
private
String sex ;
public
void
set(String name,String sex)
{
this
.name
=
name;
this
.sex
=
sex;
}
public
String get()
{
return
this
.name
+
"
----
"
+
this
.sex;
}
}
class
Pro
implements
Runnable
{
Person p
=
null
;
public
Pro(Person p)
{
this
.p
=
p;
}
public
void
run()
{
int
i
=
0
;
while
(
true
)
{
if
(i
==
0
)
{
p.set(
"
林嘉绮
"
,
"
男
"
);
i
=
1
;
}
else
{
p.set(
"
香香
"
,
"
女
"
);
i
=
0
;
}
}
}
}
class
Cus
implements
Runnable
{
Person p
=
null
;
public
Cus(Person p)
{
this
.p
=
p;
}
public
void
run()
{
while
(
true
)
{
System.out.println(p.get());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public
class
Test
{
public
static
void
main(String[] args)
{
Person p
=
new
Person();
Pro pro
=
new
Pro(p);
Cus cus
=
new
Cus(p);
new
Thread(pro).start();
new
Thread(cus).start();
}
}
这个程序的运行结果是:
上面那个程序会产生两种意外:一个是当只填入一个人的姓名而未填入这个人的性别时,消费者线程就把这个人的姓名和上个人的性别联系起来并打印输出;另一个是生产者生产多次产品,而消费者才刚开始取出一个产品,或者是未等到生产者生产出来新产品,而消费者线程就取出多次旧产品。
这样,我们先加上线程同步方法:在需要锁定的资源上加上synchronized关键字就能保证线程同步。
附代码:
class
Person
{
private
String name ;
private
String sex ;
public
synchronized
void
set(String name,String sex)
{
this
.name
=
name;
this
.sex
=
sex;
}
public
synchronized
String get()
{
return
this
.name
+
"
----
"
+
this
.sex;
}
}
class
Pro
implements
Runnable
{
Person p
=
null
;
public
Pro(Person p)
{
this
.p
=
p;
}
public
void
run()
{
int
i
=
0
;
while
(
true
)
{
if
(i
==
0
)
{
p.set(
"
林嘉绮
"
,
"
男
"
);
i
=
1
;
}
else
{
p.set(
"
香香
"
,
"
女
"
);
i
=
0
;
}
}
}
}
class
Cus
implements
Runnable
{
Person p
=
null
;
public
Cus(Person p)
{
this
.p
=
p;
}
public
void
run()
{
while
(
true
)
{
System.out.println(p.get());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public
class
Test
{
public
static
void
main(String[] args)
{
Person p
=
new
Person();
Pro pro
=
new
Pro(p);
Cus cus
=
new
Cus(p);
new
Thread(pro).start();
new
Thread(cus).start();
}
}
这个程序的运行结果是:
上面这个程序解决了第一个问题,即当只填入一个人的姓名而未填入这个人的性别时,消费者线程就把这个人的姓名和上个人的性别联系起来并打印输出的问题,但是并不能解决第二个问题。若要是想解决第二个问题,我们就要添加一个信号量,控制线程之间的调用顺序。
附代码:
public
class
Food
{
private
String name;
private
String flag;
boolean
b
=
true
;
//
为true则允许生产不允许消费
//
为false则允许消费不允许生产
public
String getName()
{
return
name;
}
public
void
setName(String name)
{
this
.name
=
name;
}
public
String getFlag()
{
return
flag;
}
public
void
setFlag(String flag)
{
this
.flag
=
flag;
}
public
synchronized
void
set(String name,String flag)
{
if
(
!
b)
{
try
{
wait();
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
this
.setName(name);
this
.setFlag(flag);
b
=
false
;
notify();
}
public
synchronized
String get()
{
if
(b)
{
try
{
wait();
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
b
=
true
;
notify();
return
"
名称:
"
+
this
.getName()
+
"
类型:
"
+
this
.getFlag();
}
}
public
class
Producer
implements
Runnable
{
private
Food food;
public
Producer(Food food)
{
this
.food
=
food;
}
public
void
run()
{
boolean
b
=
true
;
while
(
true
)
{
if
(b)
{
food.set(
"
苹果
"
,
"
水果
"
);
b
=
false
;
}
else
{
food.set(
"
茄子
"
,
"
蔬菜
"
);
b
=
true
;
}
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public
class
Customer
implements
Runnable
{
private
Food food;
public
Customer(Food food)
{
this
.food
=
food;
}
public
void
run()
{
while
(
true
)
{
System.out.println(food.get());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public
class
Test
{
public
static
void
main(String[] args)
{
Food food
=
new
Food();
Producer producer
=
new
Producer(food);
Customer customer
=
new
Customer(food);
new
Thread(producer).start();
new
Thread(customer).start();
}
}
我们看看运行结果:
综上所述,我们要想处理线程生产和消费的问题就需要进行两步操作:
1.线程同步:进行资源锁定,避免各个数据之间不匹配的问题。
2.加入信号量:通过类似于开关似的信号量来控制各个线程的调度,解决了一个线程连续多次被调用的问题。
发表于 2010-11-09 01:59
迟到的钟声
阅读(143)
评论(1)
编辑
收藏
评论
#
re: 生产消费问题
回复
更多评论
臭小子 居然FZZT
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理