黑马程序员技术交流社区

标题: 线程返回值的多线程操作问题 [打印本页]

作者: 姜蕾蕾    时间: 2014-5-18 01:22
标题: 线程返回值的多线程操作问题
用callable创建带返回值的线程方法,程序如下所示:

import java.util.concurrent.*;

class ThreadExc03 implements Callable<String>{
        private int tick = 100;
        public String call() {//又返回值的执行体
                for ( ;tick>0 ; )  {
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+tick--+"张票!");
                } return "票已告罄!";//线程执行完毕,返回String
        }
        public static void main(String[] args) {
                ThreadExc03 te3 = new ThreadExc03();
                FutureTask ft = new FutureTask<String>(te3);//用FutureTask进行包装。
                Thread t1 = new Thread(ft,"VIP窗口");//将FutureTask的对象作为线程的Target
                //Thread t2 = new Thread(ft,"普通窗口");//新开一个线程,但是没有结果,
                //Thread t3 = new Thread(ft,"应急窗口");//新开一个线程,但是没有结果,
                t1.start();
                //t2.start();
                //t3.start();
                try{
                        System.out.println(ft.get());//用FutureTask获取返回值;
                }catch(Exception e){
                  System.out.println("程序异常!");
                }
        }
}



输出结果为:

VIP窗口正在出售第100张票!
VIP窗口正在出售第99张票!
VIP窗口正在出售第98张票!
VIP窗口正在出售第97张票!
VIP窗口正在出售第96张票!
VIP窗口正在出售第95张票!
VIP窗口正在出售第94张票!
VIP窗口正在出售第93张票!
……
……
VIP窗口正在出售第8张票!
VIP窗口正在出售第7张票!
VIP窗口正在出售第6张票!
VIP窗口正在出售第5张票!
VIP窗口正在出售第4张票!
VIP窗口正在出售第3张票!
VIP窗口正在出售第2张票!
VIP窗口正在出售第1张票!
票已告罄!


问题是虽然这个方法可以建立多条线程来共享一个target,但是通过运行结果可以发现,处理Call()的线程只有一个输出,请问如何验证建立多条线程的时候,其他的线程有或者没有被执行?callable接口是否只有一个线程控制数据或者多条线程共享数据?
作者: 错过了今天    时间: 2014-5-18 12:41
implements Callable了可以创建线程吗
作者: 875588381    时间: 2014-5-18 14:22
楼主你好,很高兴和你交流。
  1. import java.util.concurrent.*;

  2. class Test001
  3. {
  4. public static void main(String[] args) throws Exception //为了方便测试,我就直接抛出异常了
  5. {
  6. TicketWindow tw = new TicketWindow(); //Callable接口的实现类

  7. ExecutorService exec = Executors.newCachedThreadPool(); //线程池
  8. /*
  9. //第一种方式
  10. Future<String> f1 = exec.submit(tw); //首先是用Future类实现的,使用Future类就必须使用ExecutorService.submit()方法
  11. Future<String> f2 = exec.submit(tw);

  12. System.out.println("f1: " + f1.get());
  13. System.out.println("f2: " + f2.get());
  14. */

  15. /*
  16. //第二种方式
  17. FutureTask<String> ft1 = new FutureTask<String>(tw); //使用了FutureTask包装。
  18. FutureTask<String> ft2 = new FutureTask<String>(tw);

  19. exec.execute(ft1); //使用的是Executor.execute()方法
  20. exec.execute(ft2);

  21. System.out.println("ft1: " + ft1.get());
  22. System.out.println("ft2: " + ft2.get());
  23. */

  24. exec.shutdown();


  25. FutureTask<String> ft1 = new FutureTask<String>(tw); //第三种方式
  26. FutureTask<String> ft2 = new FutureTask<String>(tw);

  27. new Thread(ft1, "VIP").start();
  28. new Thread(ft2, "VIP2").start();

  29. System.out.println("ft1: " + ft1.get());
  30. System.out.println("ft2: " + ft2.get());

  31. }
  32. }

  33. class TicketWindow implements Callable<String>
  34. {
  35. private int ticket = 20;
  36. public String call() {
  37. System.out.println(Thread.currentThread().getName() + "启动了。。。");
  38. for(;ticket>0;) {
  39. System.out.println(Thread.currentThread().getName()+"---售出了第:"+ticket-- + "票");
  40. }

  41. return "已经售完。";
  42. }
  43. }
复制代码

具体解释我写在了注释中。

执行效果如下:

希望对你有所帮助。

future001.png (13.74 KB, 下载次数: 18)

方式一

方式一

futuretask.png (12.5 KB, 下载次数: 22)

方式二

方式二

newthread003.png (10.41 KB, 下载次数: 20)

方式三

方式三

作者: 姜蕾蕾    时间: 2014-5-20 11:12
875588381 发表于 2014-5-18 14:22
楼主你好,很高兴和你交流。
具体解释我写在了注释中。


原来用的是线程池,我也试一下,感谢不吝赐教…
作者: 875588381    时间: 2014-5-21 08:02
姜蕾蕾 发表于 2014-5-20 11:12
原来用的是线程池,我也试一下,感谢不吝赐教…

不客气,大家互相帮助。:)
作者: 蓝雨星空    时间: 2014-5-22 07:54
不明觉厉




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2