求教一个java多线程的问题

qq_35541626 2020-03-08 01:11:33
package Thread_study; public class TestSafe_01 { public static void main(String[] args) throws InterruptedException { tiack a=new tiack(100); Thread t=new Thread(a,"阿波罗"); Thread t2=new Thread(a,"呃呃呃"); Thread t3=new Thread(a,"呵呵哒"); t.start(); t2.start(); t3.start(); } } class tiack implements Runnable{ private int tiackNumber; boolean flag=true; public tiack(int tiackNumber){ this.tiackNumber=tiackNumber; } while(flag) { test(); } } public synchronized void test(){ if(tiackNumber<0) { this.flag=false; return; } //try { //Thread.sleep(200); //} catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); //} System.out.println(Thread.currentThread().getName()+"---->"+tiackNumber+flag); tiackNumber--; } } 在test方法的if判断中,不加return,应该只能让线程最多取到-1。但是运行结果是线程取到了-1,-2,-3。很费解。
...全文
248 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_35541626 2020-03-12
  • 打赏
  • 举报
回复
引用 9 楼 paullbm的回复:
[quote=引用 8 楼 qq_35541626 的回复:]
嗯嗯 这样说我就很明白了。非常感谢解答。


明白了就结贴吧,别光发贴,不结贴啊![/quote] 结帖了,我又遇到了一个新的问题。。能不能给解答一下
paullbm 2020-03-09
  • 打赏
  • 举报
回复
引用 8 楼 qq_35541626 的回复:
嗯嗯 这样说我就很明白了。非常感谢解答。


明白了就结贴吧,别光发贴,不结贴啊!
qq_35541626 2020-03-08
  • 打赏
  • 举报
回复
引用 7 楼 paullbm的回复:
[quote=引用 6 楼 paullbm 的回复:]
[quote=引用 5 楼 qq_35541626 的回复:]
我也考虑过线程启动不同步的问题,我在线程启动t.start后面加入了t.sleep就不会出现这样的情况了。但是我的逻辑是 即使线程启动有延时,当t2启动了,t已经执行完了。那么t线程不是已经把flag修改成 false了吗,t2执行到while的时候 是不会继续执行的呀。。不知道是不是我对java多线程的机制理解有问题。请您再给予解答。谢谢


所以,你的
while (flag) {

}

这段代码放在哪里很关键!
如果这段代码本身没有放在test方法内,那么这个while(flag)还是异步执行的!
也就是说在你以为的最后一次设置为0的时候,可能3个线程都已经执行到while(flag)了,只不过这个时候flag仍然为真!
那么就都会再执行一次![/quote]


当然了,如果把上面的这个while语句放到test方法的开头,那多线程就等于变成了单线程了!因为while语句也被同步了,后面2个线程就算创建成功了,只能傻傻的等,而且一直等到程序结束也没有执行的机会。

所以,在你一开始的逻辑中,增加return是正确的处理方式!只不过你以为有问题而已![/quote] 嗯嗯 这样说我就很明白了。非常感谢解答。
paullbm 2020-03-08
  • 打赏
  • 举报
回复
引用 6 楼 paullbm 的回复:
[quote=引用 5 楼 qq_35541626 的回复:]
我也考虑过线程启动不同步的问题,我在线程启动t.start后面加入了t.sleep就不会出现这样的情况了。但是我的逻辑是 即使线程启动有延时,当t2启动了,t已经执行完了。那么t线程不是已经把flag修改成 false了吗,t2执行到while的时候 是不会继续执行的呀。。不知道是不是我对java多线程的机制理解有问题。请您再给予解答。谢谢


所以,你的
while (flag) {

}

这段代码放在哪里很关键!
如果这段代码本身没有放在test方法内,那么这个while(flag)还是异步执行的!
也就是说在你以为的最后一次设置为0的时候,可能3个线程都已经执行到while(flag)了,只不过这个时候flag仍然为真!
那么就都会再执行一次![/quote]


当然了,如果把上面的这个while语句放到test方法的开头,那多线程就等于变成了单线程了!因为while语句也被同步了,后面2个线程就算创建成功了,只能傻傻的等,而且一直等到程序结束也没有执行的机会。

所以,在你一开始的逻辑中,增加return是正确的处理方式!只不过你以为有问题而已!
paullbm 2020-03-08
  • 打赏
  • 举报
回复
引用 5 楼 qq_35541626 的回复:
我也考虑过线程启动不同步的问题,我在线程启动t.start后面加入了t.sleep就不会出现这样的情况了。但是我的逻辑是 即使线程启动有延时,当t2启动了,t已经执行完了。那么t线程不是已经把flag修改成 false了吗,t2执行到while的时候 是不会继续执行的呀。。不知道是不是我对java多线程的机制理解有问题。请您再给予解答。谢谢


所以,你的
while (flag) {

}

这段代码放在哪里很关键!
如果这段代码本身没有放在test方法内,那么这个while(flag)还是异步执行的!
也就是说在你以为的最后一次设置为0的时候,可能3个线程都已经执行到while(flag)了,只不过这个时候flag仍然为真!
那么就都会再执行一次!
qq_35541626 2020-03-08
  • 打赏
  • 举报
回复
我也考虑过线程启动不同步的问题,我在线程启动t.start后面加入了t.sleep就不会出现这样的情况了。但是我的逻辑是 即使线程启动有延时,当t2启动了,t已经执行完了。那么t线程不是已经把flag修改成 false了吗,t2执行到while的时候 是不会继续执行的呀。。不知道是不是我对java多线程的机制理解有问题。请您再给予解答。谢谢
qybao 2020-03-08
  • 打赏
  • 举报
回复
不加return,代码不是还会继续往下执行吗?所以-1,-2,-3就不难理解啊
qq_35541626 2020-03-08
  • 打赏
  • 举报
回复
引用 2 楼 paullbm的回复:
你的正确代码应该是这么写吧?


package csdn;

public class Thread_study {
public static void main(String[] args) throws InterruptedException {
tiack a = new tiack(100);
Thread t = new Thread(a, "阿波罗");
Thread t2 = new Thread(a, "呃呃呃");
Thread t3 = new Thread(a, "呵呵哒");
t.start();
t2.start();
t3.start();
}
}

class tiack implements Runnable {
private int tiackNumber;
boolean flag = true;

public tiack(int tiackNumber) {
this.tiackNumber = tiackNumber;
}

public synchronized void test() {
if (tiackNumber < 0) {
this.flag = false;
//return;
}
//try {
// Thread.sleep(200);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
System.out.println(Thread.currentThread().getName() + "---->" + tiackNumber + flag);
tiackNumber--;
}

@Override
public void run() {
while (flag) {
test();
}
}
}


首先要搞清楚的几个问题:
1.synchronized修饰词在一个方法中,就说明是同步调用方法,因此在某一段时间内只能由一个对象调用
2.由于你创建了3个线程,所以,他们对test的方法调用是抢占式的(也就是说test方法执行完一次,t,t2和t3三个线程对象都是公平去竞争)。【当然:公平竞争的前提是时间足够长,而且3个线程都已经创建完成!】
3.由于你创建了3个线程是有先后顺序的,如果执行时间太短,就会导致好像只有2个,甚至只有1个线程去调用test方法。因为创建线程也是有时间开销的。所以,要有测试效果,你得把注释的Thread.sleep(200)这几行代码放开!
4.综上所述:所以,test方法中if语句如果没有return语句的话,如果时间非常短,只有线程t创建成功并执行的话,那么,就有可能会达到你所说的效果,也就是我在第3条中所说的,只创建成功第1个线程(另2个还没来得及创建,程序就结束了),也只有1个线程去调用test方法的情况下。

如何去测试呢?那就是把我给你的修正的代码中:
tiack a=new tiack(100);
改成
tiack a=new tiack(1);
之后,多运行测试几次!!你会发现,结果并不会总一样!
好的 我先试试,我粘贴的时候可能少字儿了 , 谢谢解答
paullbm 2020-03-08
  • 打赏
  • 举报
回复
你的正确代码应该是这么写吧?


package csdn;

public class Thread_study {
public static void main(String[] args) throws InterruptedException {
tiack a = new tiack(100);
Thread t = new Thread(a, "阿波罗");
Thread t2 = new Thread(a, "呃呃呃");
Thread t3 = new Thread(a, "呵呵哒");
t.start();
t2.start();
t3.start();
}
}

class tiack implements Runnable {
private int tiackNumber;
boolean flag = true;

public tiack(int tiackNumber) {
this.tiackNumber = tiackNumber;
}

public synchronized void test() {
if (tiackNumber < 0) {
this.flag = false;
//return;
}
//try {
// Thread.sleep(200);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
System.out.println(Thread.currentThread().getName() + "---->" + tiackNumber + flag);
tiackNumber--;
}

@Override
public void run() {
while (flag) {
test();
}
}
}


首先要搞清楚的几个问题:
1.synchronized修饰词在一个方法中,就说明是同步调用方法,因此在某一段时间内只能由一个对象调用
2.由于你创建了3个线程,所以,他们对test的方法调用是抢占式的(也就是说test方法执行完一次,t,t2和t3三个线程对象都是公平去竞争)。【当然:公平竞争的前提是时间足够长,而且3个线程都已经创建完成!】
3.由于你创建了3个线程是有先后顺序的,如果执行时间太短,就会导致好像只有2个,甚至只有1个线程去调用test方法。因为创建线程也是有时间开销的。所以,要有测试效果,你得把注释的Thread.sleep(200)这几行代码放开!
4.综上所述:所以,test方法中if语句如果没有return语句的话,如果时间非常短,只有线程t创建成功并执行的话,那么,就有可能会达到你所说的效果,也就是我在第3条中所说的,只创建成功第1个线程(另2个还没来得及创建,程序就结束了),也只有1个线程去调用test方法的情况下。

如何去测试呢?那就是把我给你的修正的代码中:
tiack a=new tiack(100);
改成
tiack a=new tiack(1);
之后,多运行测试几次!!你会发现,结果并不会总一样!
paullbm 2020-03-08
  • 打赏
  • 举报
回复
你的代码真牛B:

while(flag) {
test();
}
这段代码不在类的某个方法中,也能编译通过?

另外,tiack实现了Runnable接口,不用覆盖run方法?

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧