黑马程序员技术交流社区
标题:
线程通信问题
[打印本页]
作者:
て淡莣了陌生
时间:
2013-4-27 16:50
标题:
线程通信问题
本帖最后由 て淡莣了陌生 于 2013-4-28 08:36 编辑
class Demo1_Notify {
public static void main(String[] args) {
final Printer p = new Printer();
new Thread(){
public void run() {
while(true)
try {
p.print1();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run() {
for(;;)
try {
p.print2();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run() {
for(;;)
try {
p.print3();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
class Printer {
private int flag = 1;
public synchronized void print1() throws Exception {
if (flag != 1)
wait();
System.out.print("好");
System.out.print("好");
System.out.print("学");
System.out.print("习");
System.out.print("\r\n");
flag = 2;
notifyAll();
}
public synchronized void print2() throws Exception {
if (flag != 2)
wait();
System.out.print("天");
System.out.print("天");
System.out.print("向");
System.out.print("上");
System.out.print("\r\n");
flag = 3;
notifyAll();
}
public synchronized void print3() throws Exception {
if (flag != 3)
wait();
System.out.print("A");
System.out.print("l");
System.out.print("r");
System.out.print("e");
System.out.print("a");
System.out.print("d");
System.out.print("\r\n");
flag = 1;
notifyAll();
}
}
这段代码执行后为什么没有按照顺序来打印呢,研究了大半天了都没找出哪里出了问题,哪位大神能指点一下迷津啊,谢谢了啊!!!
作者:
java冬冬
时间:
2013-4-27 17:10
本帖最后由 java冬冬 于 2013-4-27 18:21 编辑
代码修改如下:{:soso_e152:}
class Demo1_Notify {
public static void main(String[] args) {
final Printer p = new Printer();
new Thread(){
public void run() {
while(true)
try {
p.print1();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run() {
for(;;)
try {
p.print2();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run() {
for(;;)
try {
p.print3();
} catch(Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
class Printer {
private int flag = 1;
public synchronized void print1() throws Exception {
while (flag != 1)
wait();
System.out.print("好");
System.out.print("好");
System.out.print("学");
System.out.print("习");
System.out.print("\r\n");
flag = 2;
notifyAll();
}
public synchronized void print2() throws Exception {
while (flag != 2)
wait();
System.out.print("天");
System.out.print("天");
System.out.print("向");
System.out.print("上");
System.out.print("\r\n");
flag = 3;
notifyAll();
}
public synchronized void print3() throws Exception {
while(flag != 3)
wait();
System.out.print("A");
System.out.print("l");
System.out.print("r");
System.out.print("e");
System.out.print("a");
System.out.print("d");
System.out.print("\r\n");
flag = 1;
notifyAll();
}
}
复制代码
运行结果:
2.jpg
(11.63 KB, 下载次数: 0)
下载附件
2013-4-27 18:20 上传
作者:
杨同旺
时间:
2013-4-27 17:54
本帖最后由 杨同旺 于 2013-4-27 17:55 编辑
把以上代码中的if,全部改为while,便能解决问题,
原因是由于,先打印print1,此时print3等待,
当print1打印完成后,print3恰好被唤醒,此时print3将不会返回去再判断if,而是不再判断直接就打印了,
所以,需要加上
while
,print3在打印之前,将会回去判断一下while(flag!=3),结果就正确了.
作者:
Miss小强
时间:
2013-4-27 18:07
本帖最后由 黄玉昆 于 2013-4-27 19:50 编辑
楼上的说的对,补充点:
为什么要用while,那时因为会出现假唤醒的现象,本来没有被notify,
被唤醒了之后没有判断标记,就容易出问题;
给你一个我写的吧:
package cn.itcast.concurrent;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Business {
/* *
* 需求:
* 有三个线程:一个主线程,两个子线程A,B;
* 主线程循环20次,A线程循环30次,B循环40次;
* 如此交替50次;即主---》A---》B;
* 思路:
* 可以定义一个锁,在一个锁上获得三个condition分别代表主,A,B;
* 定义一个int变量:作为一个标记,来标识三个线程是否可以执行;
* 1---》主 2---》A 3---》B;
*/
private Lock lock = new ReentrantLock();
private int flag = 1;
private Condition main_condition = lock.newCondition();
private Condition a_condition = lock.newCondition();
private Condition b_condition = lock.newCondition();
public void main(int i) {
lock.lock();
try {
while (flag != 1) {
main_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName() + "main loop" + j + "of" + i);
}
flag=2;
a_condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public void subA(int i) {
lock.lock();
try{
while(flag!=2){
a_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName() + "A loop" + j + "of" + i);
}
flag=3;
b_condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally{
lock.unlock();
}
}
public void subB(int i) {
lock.lock();
try{
while(flag!=3){
b_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName() + "B loop" + j + "of" + i);
}
flag=1;
main_condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally{
lock.unlock();
}
}
}
复制代码
作者:
Miss小强
时间:
2013-4-27 18:07
本帖最后由 黄玉昆 于 2013-4-27 19:52 编辑
package cn.itcast.concurrent;
public class ThreeThreadcommunicati {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
business.subA(i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
business.subB(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2