java

登录 | 注册
首页 精选版块  论坛帮助 论坛牛人 论坛地图 专家问答
CSDN > CSDN论坛 > Java > Java EE
返回列表
管理菜单 结帖 发帖 回复 关注关注
多线程 继承Runable接口,怎样将线程运行完后的结果返回到主线程 [问题点数:40分,结帖人undertones1985] 快速回复只显示楼主关注帖子
多线程 继承Runable接口,怎样将线程运行完后的结果返回到主线程 [问题点数:40分,结帖人undertones1985]   收藏
undertones1985

undertones1985
undertones1985
本版等级:T1
结帖率:97.5%
楼主 发表于: 2010-06-08 14:45:19
      大家好,我现在做一个项目只能用java 1.4版本,因此没办法用1.5版本中的Callable接口给主线程提供返回值。
      我做的是将各个独立的任务放在多个线程中同时进行,并希望他们在结束后将结果返回到主线程,请问这该怎么做啊,膜拜各路大侠给我指点指点!
更多 0 分享到:
相关主题推荐:

对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 回复次数:26
luozhangwen

luozhangwen
luozhangwen
本版等级:T5
#1 得分:0 回复于: 2010-06-08 14:48:05

对我有用[0] 丢个板砖[1] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#2 得分:0 回复于: 2010-06-08 14:59:57
天马行空--- 我的qq的签名也是这个  蛮巧的。

主线程中创建一个数据访问安全的对象A,主线程启动的线程thread2初始化时,A作为thread2的初始化参数,thread2在run方法中把操作结果返回给对象A。

主线程在thread2未完成操作时等待就好了,直到等待的thread2运行结束 进行下步操作。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
QQCrazyBoy

QQCrazyBoy
哈特中尉
本版等级:T5
#3 得分:5 回复于: 2010-06-08 15:01:20
自定义的线程跑玩了就会自动去执行主线程啊!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
Silence_Smile

Silence_Smile
Silence_Smile
本版等级:T5
#4 得分:5 回复于: 2010-06-08 15:06:33
自定义回调接口,子线程执行完后通过回调接口调用主线程中的回调方法
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#5 得分:0 回复于: 2010-06-08 15:10:01
to QQCrazyBoy
引用
  自定义的线程跑玩了就会自动去执行主线程啊!


你自己测试下,是这样的吗?
线程和线程之间是独立的。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
wwj85523

wwj85523
俊哥123
本版等级:T2
#6 得分:10 回复于: 2010-06-08 15:47:02
主线程里放一个Hashtable ,业务线程把返回结果放进去,主线程里取。
这样就OK了,另Hashtable是线程安全的,不需要另外加锁
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
guliangliang

guliangliang
艾瑞儿
本版等级:T2
#7 得分:0 回复于: 2010-06-08 16:57:47
学识浅薄,不太懂,学习下
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
potahai

potahai
potahai
本版等级:T3
#8 得分:0 回复于: 2010-06-08 17:21:38
继续关注
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
undertones1985

undertones1985
undertones1985
本版等级:T1
#9 得分:0 回复于: 2010-06-08 18:42:55
楼上的说的方法我还是不太懂,把问题再明确一下:
     每个线程结束都会得到一个List类型的数据,然后主线程需要创建一个更大的List类型的变量,把各个子线程的List数据保存进去,我就是这不太懂怎么实现,咋样创建Hashtable实现呢,况且我的进程数是根据输入任务不同,需要变化的,请再次赐教,在线等!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
undertones1985

undertones1985
undertones1985
本版等级:T1
#10 得分:0 回复于: 2010-06-08 18:48:24
引用 2 楼 moshalanye 的回复:
天马行空--- 我的qq的签名也是这个 蛮巧的。

主线程中创建一个数据访问安全的对象A,主线程启动的线程thread2初始化时,A作为thread2的初始化参数,thread2在run方法中把操作结果返回给对象A。

主线程在thread2未完成操作时等待就好了,直到等待的thread2运行结束 进行下步操作。


请问一下,Runable接口中的run()函数是不允许有返回值的,如何返回?谢谢!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
mhl1003

mhl1003
mhl1003
本版等级:T2
#11 得分:10 回复于: 2010-06-08 19:15:15
引用 10 楼 undertones1985 的回复:
引用 2 楼 moshalanye 的回复:
天马行空--- 我的qq的签名也是这个 蛮巧的。

主线程中创建一个数据访问安全的对象A,主线程启动的线程thread2初始化时,A作为thread2的初始化参数,thread2在run方法中把操作结果返回给对象A。

主线程在thread2未完成操作时等待就好了,直到等待的thread2运行结束 进行下步操作。


请问一下,Run……

设置一个static静态的变量就可以实现结果共享了。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
katasoft

katasoft
katasoft
本版等级:T4
#12 得分:0 回复于: 2010-06-08 19:16:10
所有子线程都将结果写到公共的缓冲区中(注意并发问题),在启动子线程后,将主线程挂起(wait),直到所有子线程结束后唤醒主线程,此时便可以获取缓冲区中各个子线程写入的内容(相当于子线程饭后的结果)。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
undertones1985

undertones1985
undertones1985
本版等级:T1
#13 得分:0 回复于: 2010-06-08 19:52:10
引用 11 楼 mhl1003 的回复:
引用 10 楼 undertones1985 的回复:

引用 2 楼 moshalanye 的回复:
天马行空--- 我的qq的签名也是这个 蛮巧的。

主线程中创建一个数据访问安全的对象A,主线程启动的线程thread2初始化时,A作为thread2的初始化参数,thread2在run方法中把操作结果返回给对象A。

主线程在thread2未完成操作时等待就好了,直到等待的thr……



我试过了,返回的是空值。静态变量只是对于许多类的实例可以这样实现数据共享,但是在多线程中式一个线程一个类的实例,这样做是不行的!!!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#14 得分:10 回复于: 2010-06-08 20:40:33
汗!  楼主我随便写下  大概是这个思路,我写的是伪代码。
你自己再去改下吧

main(){
  Map datas = new Hashedtable();
  MyThreadRun run = new MyThreadRun();
  run.setDatas(datas);
  Thread tt =  new Thread(run);
  tt.start();
 
  while(!"result is ok".equal(datas.get("status"))){
     try{
       Thread.sleep(10000);
     }catch(Exception){
       //todo
     }
  }
  //或者使用join 具体的看下api
  tt.join();

   Object result = run.get("result");
   //dosomething
}

static Class MyThreadRun implements Runable{
   Hashedtable datas;
   public void setData(Map data){
       this.datas = data;
   }

   run(){
      //execute get the result
      this.datas.put("result",result);
      this.datas.put("status","result is ok");
   }
}
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
wwj85523

wwj85523
俊哥123
本版等级:T2
#15 得分:0 回复于: 2010-06-08 21:33:11
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
main(){
  HashTable datas = new HashTable();
MainThread  mainThread=new MainThread(datas);
mainThread.start();

//这里的子线程可以多个
  MyThreadRun run = new MyThreadRun();
  run.setDatas(datas);
  Thread tt = new Thread(run);
  tt.start(); 
   
}

Class MyThreadRun implements Runable{
  Hashedtable datas;
  public void setData(Map data){ 
  this.datas = data;
  }

  run(){
  //execute get the result
  this.datas.put("result",result);
  this.datas.put("status","result is ok");
  }
}

class MainThread extends Thread{
Hashtable table;
   public MainThread(Hashtable table){
     this.table=table;
}
public void run(){
   while(true){
Thread.sleep(1000l);
List result=table.remove("result");
if(result!=null){
  //dosomething
}

}

}
}


参照楼上的代码,随便改下,楼上的大哥不要生气哈。- -!!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
xusenjian

xusenjian
xusenjian
本版等级:T2
#16 得分:0 回复于: 2010-06-08 21:54:34
概是这个思路,我写的是伪代码
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#17 得分:0 回复于: 2010-06-09 08:54:51
to wwj85523

你该成三个线程了,main方法执行的也有一个线程,不过这么写楼主可能更好理解。

不过
引用
  while(true){
Thread.sleep(1000l);
List result=table.remove("result");
  if(result!=null){
  //dosomething
}


要改一下,这样写线程不会死了,一般都是使用状态量来控制 while(isAlive)
  if(result!=null){
  //dosomething
  isAlive = false;
}

这样比较好,也可以使用Thread 内置的状态 interrupted
while(isInterrupted()){
//dosomething

interrupted();
}

对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
undertones1985

undertones1985
undertones1985
本版等级:T1
#18 得分:0 回复于: 2010-06-09 10:15:41
引用 14 楼 moshalanye 的回复:
汗! 楼主我随便写下 大概是这个思路,我写的是伪代码。
你自己再去改下吧

main(){
  Map datas = new Hashedtable();
  MyThreadRun run = new MyThreadRun();
  run.setDatas(datas);
  Thread tt = new Thread(run);
  tt.start();
 
……


你这样写是针对只有一个子线程的,如果有多个子线程在同时执行,而且每个子线程结束任务并返回的时间是不同的,但是都返回值的的Hashtable表中的状态标记 "status" = finish.这样对于你的程序就只能返回最开始的一个线程值了。
还有没有更好的方法呢?谢谢
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
SDMRauquin

SDMRauquin
SDMRauquin
本版等级:T6
#19 得分:0 回复于: 2010-06-09 10:23:52
要带返回值的线程。需要JDK1.5以上

有Callable 这个
详细的用法你去看资料。
给你看看我简单的应用。
根据返回值判断是否跳出循环的
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
                Callable callable = new ReadInfoTimerTask(unicode, messages);
                Future future = null;
                int i = 1;
                while(messages[2].trim().equals(""))    //unicode is empty
                {
                    future = SSP.scheduledExecutor.schedule(callable, scanTime, TimeUnit.SECONDS);
                    messages = (String[])future.get();
                    i++;
                    if(i>scanNO)
//                        messages[3] = "timeOut";
                        break;
                }


这个是线程
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ReadInfoTimerTask implements Callable {
    
    private String key;
    private String[] messages;

    public ReadInfoTimerTask(String unicode, String[] messages){
        this.key = unicode;
        this.messages = messages;
    }

    public String[] call() throws Exception{
        if(SSP.resultList.get(key)!=null)
        {
            messages = SSP.resultList.get(key);      
            SSP.resultList.remove(key);
        }
        return messages;
    }

}


这只是部分的代码,不能直接复制使用,仅供参考
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
SDMRauquin

SDMRauquin
SDMRauquin
本版等级:T6
#20 得分:0 回复于: 2010-06-09 10:27:41
说了才看见问题。。不能JDK1.5

当我没说。。

对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#21 得分:0 回复于: 2010-06-09 10:30:48
楼主这个是伪代码,你怎么去判定是不是子线程都执行完毕,完全可以自己设计嘛。

例如:引用计数器的方式。main thread 开启几个 son thread,就在计数器中+ji,
son thread 运行结束,对计数器-1,当减到0的时候,main thread 判定 son thread 执行完毕,
开始执行。

引用计数器 就是一个线程共享的 线程安全的数据资源。之前的代码也给你了,你可以参照。

引用计数器,在 lucene 2.32中 IndexReader 有引用计数器代码,当然有计数器代码的地方应该很多。

你可以参照下。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
SDMRauquin

SDMRauquin
SDMRauquin
本版等级:T6
#22 得分:0 回复于: 2010-06-09 10:36:47
public static ConcurrentHashMap<String, List[]> resultList = new ConcurrentHashMap<String, List[]>();      //ConcurrentHashMap支持多线程并发

每个线程创建的时候,生成一个UniID保存成key。
子线程返回的结果,根据这个key保存进resultList。

主线程每隔一段时间去遍历这个list
for(Map.Entry<String, List[]> entry : XXX.resultList.entrySet())
{
if(XXX)
{
method(entry.getValue(),entry.getKey());
}
XXX.resultList.remove(entry.getKey());
}
处理完移出list
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
moshalanye

moshalanye
宁静-夏天
本版等级:T5
#23 得分:0 回复于: 2010-06-09 11:08:15
ConcurrentHashMap 不仅仅是支持多线程并发了,它还提供了散列 sagement 的实现方式,分离了 segement 访问的同步锁,从而加速了同步访问速度。
改进了以往 HashTable 或者 Collections.syn..(Map) 只提供一个 segement 和 单一的同步锁的情况。

楼上的朋友很热衷 concurrent 包列。连续的几个建议都是使用这个包。

这个地方没必要使用 ConcurrentHashMap,有点杀鸡用牛刀的感觉,简洁就好,自己设计成线程安全就可以了。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
BearKin

BearKin
BearKin
本版等级:T7
Blank
#24 得分:0 回复于: 2010-06-09 11:48:57
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package thread;

import java.util.ArrayList;
import java.util.List;

public class NoCallable {
    public static void main(String[] args) {
        List<TestThread> list = new ArrayList<TestThread>();
        for (int i = 0; i < 4; i++) {
            TestThread testThread = new TestThread(9999999999L);
            testThread.start();
            list.add(testThread);
        }
        boolean isLoop = true;
        while (isLoop) {
            try {
                Thread.sleep(1000 * 1);
                isLoop = false;
                for (TestThread testThread : list) {
                    System.out.println(testThread.isAlive());
                    if (testThread.isAlive()) {
                        isLoop = true;
                    }
                }
                System.out.println();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        for (TestThread testThread : list) {
            System.out.println(testThread.getResult());
        }
    }
}

class TestThread extends Thread {

    private long loopNum;
    private int result = 0;

    public TestThread(long loopNum) {
        this.loopNum = loopNum;
    }

    @Override
    public void run() {
        long currentNum = loopNum;
        boolean isOver = false;
        while (!isOver) {
            if (currentNum < 0) {
                isOver = true;
            }
            result++;
            currentNum = currentNum - 2;
        }
    }

    public long getLoopNum() {
        return loopNum;
    }

    public void setLoopNum(long loopNum) {
        this.loopNum = loopNum;
    }

    public int getResult() {
        return result;
    }

    public void setResult(int result) {
        this.result = result;
    }

}


这个不用Callable 线程这方面俺知识太少了 所以你凑货着看吧。。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
undertones1985

undertones1985
undertones1985
本版等级:T1
#25 得分:0 回复于: 2010-06-11 21:33:50
谢谢大家,我已经搞定了,就如同上面说的那样。给线程类设置一个静态变量,就可以实现线程间的数据共享,然后再创建一个HashTable就可以实现将此线程内的数据传递给主线程。最后对刚起的各个子线程利用Join()方法,使他们全部允许完再回到主线程,就可以完成我的功能,在此谢谢大家。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
purple117

purple117
purple117
本版等级:T1
#26 得分:0 回复于: 2012-05-18 13:52:32
可以贴出你的能成功实现的代码吗? 谢谢
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
返回列表
管理菜单 结帖 发帖 回复 关注关注
本帖子已过去太久远了,不再提供回复功能。
公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈
网站客服杂志客服微博客服[email protected]|北京创新乐知信息技术有限公司 版权所有|江苏乐知网络技术有限公司 提供商务支持
京 ICP 证 070598 号|Copyright © 1999-2014, CSDN.NET, All Rights Reserved GongshangLogo

你可能感兴趣的:(多线程)