刚接触多线程 很多东西很晕,譬如网上这段代码,请教一下:其中有一段对这段代码的点评:“出现了重复读取的问题,也肯定有重复覆盖的问题”
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<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100
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<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100
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)才能达到你的目的
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();//叫醒
}
}
加上了Thread.sleep(100)之后输出结果会有
Rollen<===>20
ChunGe<===>100
间隔出现但为什么生产者线程占用了set和get方法后,消费者线程还能调用get方法,这两个方法不是被synchronized锁住了吗?
这里消费者为什么还能调用get方法?不是被生产者锁住了吗?
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把整段括起来
明白了 是在调用set方法时候才锁住,但是一调用完的时候,锁就释放了,另一个线程可以调用这个方法了!