当前位置:编程学习 > JAVA >>

多线程大牛请进!

小弟初试多线程就碰壁了。恳求大牛指点迷津。问题如下:
1.任务类:
  public class Task implements Runnable{
private static int id=0;
private final int threadID=id++;

public Task(){
}
public void run(){
    System.out.println("threadID="+threadID);
    System.out.println("id="+id);
}
}
2.程序入口:
 public class APPMain {
public static void main(String[] args){
ExecutorService es=Executors.newFixedThreadPool(1000);
for(int i=0;i<10;i++){
es.execute(new Task());
}
es.shutdown();
}
}
3.Eclipse中一次执行的结果:
threadID=0
id=5
threadID=1
id=10
threadID=2
threadID=3
id=10
threadID=5
id=10
threadID=7
id=10
threadID=6
id=10
threadID=8
id=10
threadID=4
id=10
id=10
threadID=9
id=10
4.跪求大牛指点各种道理。为什么id没有得到同步,ThreadID却得到了同步? --------------------编程问答-------------------- static静态的是多个对象共享的。
因为是多线程,所以我觉得执行的顺序应该是
先new Task()若干个对象出来,这时候
private static int id=0;
private final int threadID=id++;
就已经被赋值了,但是run方法还没有被执行,threadID各个对象之间不影响,但是id是共享的,所以会改变,最后输出值会一样。
然后这若干个对象在一起执行run方法输出。 --------------------编程问答-------------------- 创建N个Task有点怪,不知道你要达到什么目的,可以给你解释下你的代码为什么出现这个结果。

for(int i=0;i<10;i++){
   es.execute(new Task()); 
}

会产生10个实例,第一个实例d为0,threadID也为0,由于d为static,第二个实例d为1,threadID为1,以此类推10个实例。
线程池执行实例的start()方法和创建实例的先后没准,你这个是创建好4个实例后,才执行第一个实例的start方法,就会出现:
threadID=0
id=5
线程池是同步的,所以10个线程执行没有先后,就会出现:
threadID=8
id=10
threadID=4
第9个创建的实例执行start后,第5个创建的实例才执行start。

如有错误请纠正。
--------------------编程问答-------------------- ThreadID同步是一定的,因为其声明为private final int threadID=id++;不是共享的。而id声明为static,则其为共享的,调用输出时,其id也许已经被++了。 --------------------编程问答-------------------- 楼上的都是正解。start()不是调用就能立即运行的(具体得看情况),有可能需要一段时间后才运行。你正好要到了延迟,才导致一系列疑问。 --------------------编程问答-------------------- synchronized (this) {} --------------------编程问答-------------------- 上面说的都有些道理,我整理了下大家的意见。
1、id这个变量是一个共享资源,所谓“共享资源”,指的是多个线程可以同时访问的数据结构、文件等信息实体。
2、你这段程序可以分为2段来看,一段是运算,一段是输出。

3、你代码中开启了10个线程访问共享资源id,对他进行运算。当第8个线程运算后。
4、第6个和第7个线程运行到输出,但是此时id已经被第8个线程重新计算为9,所以第6个和第7个线程输出的结果是9。

代码做了下改动,应该有更好的方法。请参考
package com.test;

public class Task implements Runnable {
private static int id = 0;
private int threadID = 0;
public Task() {
}

public void run() {
synchronized(this){
threadID = id;
System.out.println("id=" + id++);
System.out.println("threadID=" + threadID);
}
}
}
--------------------编程问答--------------------
引用 6 楼 u010926176 的回复:
上面说的都有些道理,我整理了下大家的意见。
1、id这个变量是一个共享资源,所谓“共享资源”,指的是多个线程可以同时访问的数据结构、文件等信息实体。
2、你这段程序可以分为2段来看,一段是运算,一段是输出。

3、你代码中开启了10个线程访问共享资源id,对他进行运算。当第8个线程运算后。
4、第6个和第7个线程运行到输出,但是此时id已经被第8个线程重新计算为9,所以第6个和第7个线程输出的结果是9。

代码做了下改动,应该有更好的方法。请参考
package com.test;

public class Task implements Runnable {
private static int id = 0;
private int threadID = 0;
public Task() {
}

public void run() {
synchronized(this){
threadID = id;
System.out.println("id=" + id++);
System.out.println("threadID=" + threadID);
}
}
}


那岂不是会这样啊:10个实力new 好了,但是10个线程执行顺序不确定,而id会递增顺序输出啊...?
还没代码验证。 --------------------编程问答--------------------
引用 7 楼 klov001 的回复:
Quote: 引用 6 楼 u010926176 的回复:

上面说的都有些道理,我整理了下大家的意见。
1、id这个变量是一个共享资源,所谓“共享资源”,指的是多个线程可以同时访问的数据结构、文件等信息实体。
2、你这段程序可以分为2段来看,一段是运算,一段是输出。

3、你代码中开启了10个线程访问共享资源id,对他进行运算。当第8个线程运算后。
4、第6个和第7个线程运行到输出,但是此时id已经被第8个线程重新计算为9,所以第6个和第7个线程输出的结果是9。

代码做了下改动,应该有更好的方法。请参考
package com.test;

public class Task implements Runnable {
private static int id = 0;
private int threadID = 0;
public Task() {
}

public void run() {
synchronized(this){
threadID = id;
System.out.println("id=" + id++);
System.out.println("threadID=" + threadID);
}
}
}


那岂不是会这样啊:10个实力new 好了,但是10个线程执行顺序不确定,而id会递增顺序输出啊...?
还没代码验证。


引用 7 楼 klov001 的回复:
Quote: 引用 6 楼 u010926176 的回复:

上面说的都有些道理,我整理了下大家的意见。
1、id这个变量是一个共享资源,所谓“共享资源”,指的是多个线程可以同时访问的数据结构、文件等信息实体。
2、你这段程序可以分为2段来看,一段是运算,一段是输出。

3、你代码中开启了10个线程访问共享资源id,对他进行运算。当第8个线程运算后。
4、第6个和第7个线程运行到输出,但是此时id已经被第8个线程重新计算为9,所以第6个和第7个线程输出的结果是9。

代码做了下改动,应该有更好的方法。请参考
package com.test;

public class Task implements Runnable {
private static int id = 0;
private int threadID = 0;
public Task() {
}

public void run() {
synchronized(this){
threadID = id;
System.out.println("id=" + id++);
System.out.println("threadID=" + threadID);
}
}
}


那岂不是会这样啊:10个实力new 好了,但是10个线程执行顺序不确定,而id会递增顺序输出啊...?
还没代码验证。


嗯 这么写完后 间接的就编程了 串行的了。 --------------------编程问答-------------------- 不结贴是个挺烦的事情~~~
补充:Java ,  Java EE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,