读书人

多线程 有货色不明白

发布时间: 2012-12-17 09:31:40 作者: rapoo

多线程 有东西不明白
刚接触多线程 很多东西很晕,譬如网上这段代码,请教一下:

其中有一段对这段代码的点评:“出现了重复读取的问题,也肯定有重复覆盖的问题”
1.请问为什么会这这样?


2.因为Info的set方法和get方法都加上了synchronized ,所以当又一个线程调用了其中的一个方法时候(比如set),另外一个方法(比如get)也就被这个线程占用,不能被别的线程占用,这样理解对不?

3.不知道为什么会出现这样的运行结果,生产者线程不是已经占用Info的set和get ,然后在循环中一直把名字和年龄改来改去吗?消费者线程为什么还能输出每次生产者线程修改的结果?
这个程序的运行过程究竟是咋样的?谢谢前辈


class Info {

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public synchronized void set(String name, int age){
this.name=name;
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
this.age=age;
}

public synchronized void get(){
try{
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.getName()+"<===>"+this.getAge());
}
private String name = "Rollen";
private int age = 20;
}

/**
* 生产者
* */
class Producer implements Runnable {
private Info info = null;

Producer(Info info) {
this.info = info;
}

public void run() {
boolean flag = false;
for (int i = 0; i < 25; ++i) {
if (flag) {

this.info.set("Rollen", 20);
flag = false;
} else {
this.info.set("ChunGe", 100);


flag = true;
}
}
}
}

/**
* 消费者类
* */
class Consumer implements Runnable {
private Info info = null;

public Consumer(Info info) {
this.info = info;
}

public void run() {
for (int i = 0; i < 25; ++i) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
this.info.get();
}
}
}

/**
* 测试类
* */
public class hello {
public static void main(String[] args) {
Info info = new Info();
Producer pro = new Producer(info);
Consumer con = new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
}
}

运行结果:
Rollen<===>20

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

Rollen<===>20

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100




[最优解释]
for (int i = 0; i < 25; ++i) {
if (flag) {

this.info.set("Rollen", 20);
flag = false;
} else {
this.info.set("ChunGe", 100);


flag = true;
}
}

这段代码运行的太快了,瞬间就结束了,也就是说,他根本没有等消费者使用,就运行完毕了。你应该弄一个队列,或者堆栈,把生产的数据挨个放进去,消费者则挨个的获取。
有个Queue的类适合这个
[其他解释]
同楼上,按你的代码来看,估计要在
for (int i = 0; i < 25; ++i) {
if (flag) {

this.info.set("Rollen", 20);
flag = false;
} else {
this.info.set("ChunGe", 100);
flag = true;
}
}
里面加一个Thread.sleep(100)才能达到你的目的
[其他解释]


for (int i = 0; i < 25; ++i) { if (flag) { this.info.set("Rollen", 20); flag = false; } else { this.info.set("ChunGe", 100); flag = true; } }

这个锁,只有你调用
this.info.set("Rollen", 20);
和 this.info.set("ChunGe", 100);
的时候会锁住,这两行执行完了,锁就放开了
除非你是synchronized把整段括起来

[其他解释]
提供一多线程例子


public class Yi_Hong_Courtyard {

public static void main(String[] args) {
// TODO Auto-generated method stub
Yi_Hong_Courtyard yunxing = new Yi_Hong_Courtyard();

}


Yi_Hong_Courtyard(){

Procuress procuress = new Procuress();

Miss miss = new Miss(procuress);
Piao_Guest guest = new Piao_Guest(procuress);

Thread t_miss = new Thread(miss);
Thread t_guest = new Thread(guest);

Produce_Business();//内容介绍{函数在29--31行}

t_miss.start();
t_guest.start();

}

public void Produce_Business(){
System.out.println("欢迎光临大日本怡红院-----祝您玩的愉快(xi wang nin zai e gao zhong xue hui duo xian cheng)");


}
}

//小姐...给钱就干
class Miss implements Runnable{

Procuress procuress;

public Miss(Procuress procuress){
this.procuress = procuress;
}

@Override
public void run() {
// TODO Auto-generated method stub
int i = 1;
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(i == 1){
try {
procuress.fenpen_miss("苍井空","500日元");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
try {
procuress.fenpen_miss("甜心花子", "800日元");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
i = (i+1) % 2;
}
}

}

//嫖客...花钱就嫖
class Piao_Guest implements Runnable{

Procuress procuress;

public Piao_Guest(Procuress procuress){
this.procuress = procuress;
}

@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
procuress.make_love();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

//老鸨...统一管理小姐内部工作
class Procuress{

private String miss = null;
private String price = null;
private boolean jie_Guest = true;

public synchronized void fenpen_miss(String miss,String price) throws InterruptedException{
if(!jie_Guest)
wait();//等待
this.miss = miss;
this.price = price;
jie_Guest = false;
notify();//叫醒
}

public synchronized void make_love() throws InterruptedException{
if(jie_Guest)
wait();//等待
System.out.println("接客小姐:"+miss);
System.out.println("接客价格:"+price);
System.out.println(" "+" "+" "+" "+" "+" "+" "+" "+" "+" "+miss+"工作完事"+"准备接客... ...");
System.out.println("****************************************");
jie_Guest = true;
notify();//叫醒
}
}


[其他解释]
引用:
同楼上,按你的代码来看,估计要在
for (int i = 0; i < 25; ++i) {
if (flag) {

this.info.set("Rollen", 20);
flag = false;


……



加上了Thread.sleep(100)之后输出结果会有
Rollen<===>20
ChunGe<===>100
间隔出现

但为什么生产者线程占用了set和get方法后,消费者线程还能调用get方法,这两个方法不是被synchronized锁住了吗?
[其他解释]
引用:
for (int i = 0; i < 25; ++i) {
if (flag) {

this.info.set("Rollen", 20);
flag = false;
} else {
……


这里消费者为什么还能调用get方法?不是被生产者锁住了吗?
[其他解释]
为什么Info参数可以共用?
[其他解释]
三楼人才啊。
[其他解释]
引用:
Java code?12 for (int i = 0; i < 25; ++i) { if (flag) { this.info.set("Rollen", 20); flag = false; } else { ……


明白了 是在调用set方法时候才锁住,但是一调用完的时候,锁就释放了,另一个线程可以调用这个方法了!

读书人网 >J2SE开发

热点推荐