1. executor当然可以装Thread,你试一下就知道了
2. FutureTask is a Runnable
3. Thread不能装Callable是因为没有意义。没有让你拿结果的接口。
【 在 PlutoKey (铠甲勇士) 的大作中提到: 】
: 标 题: 线程池里面竟然不能装线程
: 发信站: 水木社区 (Mon Dec 6 18:46:03 2021), 站内
:
: ExecutorService es = Executors.newFixedThreadPool(16);
: es.submit(runable);
: es.submit(callable);
:
: 现象一:
: 线程池Executor不能装线程Thread,只能装Runable和Callable。
:
: ===== =====
:
: Thread t = new Thread();
: Thread t = new Thread(runable);
: Thread t = new Thread(futuretask);
:
: 现象二:
: 线程Thread不能装Callable,只能装Thread和Runable和FutureTask。
:
: ===== =====
:
: # Callable要装进Thread怎么办?
: 先把Callable装进FutureTask,再FutureTask装进Thread。这是FutureTask存在的唯一意义。
: 如果用线程池,线程池可以直接装进Callable,那么FutureTask就用不到了。
:
: ===== =====
:
: # 如何合并多个线程的结果?
:
: 有两种方法
: 一是 Runable + CountDownLatch
: 二是 Callable + Future
: 两种都要用到 Collections.synchronizedList
:
: 最终合并的结果会被多个线程同时写入,所以要用synchronized的版本。
: List<T> results = Collections.synchronizedList(new ArrayList<>());
:
: 第一种里面 有一个计数器CountDownLatch,
: 每个线程完成的时候就把计算器减一,当计数器等于零的时候就知道所有线程都执行完了。
:
: CountDownLatch和CycleBarrier有什么区别?
: 没区别,CountDownLatch是倒数的,CycleBarrier是正数的。
:
: 第二种里面 不需要去知道所有线程都执行完。
: 因为future.get()会天然的等它执行完。
: List<Future<T>>装下每个线程的Future<T>。
: 然后分别future.get() 再装到总的List<T> results里面。
:
: future.get()不会阻塞吗?
: 前面所有线程都起来了,future.get()只会阻塞当前一个线程。
: 第一个线程当然会阻塞,但是当你第一个线程执行完成,其他线程也差不多快执行完了或者已经执行完了,
: 所以其他线程的future.get()不会有第一个那么久,可以忽略不计。
:
: 有了Future,就不需要关心全部线程是否都执行完了。
:
: 第一种和第二种有什么区别?
: Runable是没有返回值的,Callable有返回值。
:
: Runable没返回值很好解决,每个Runable线程都把结果写到公共区,自然就不需要返回值了。
: Callable则可以单独返回自己的结果,但是这个结果最后也是要汇总的,所以也不见得就省了事。
:
: Java自带了很多加锁的工具 比如Collections.synchronizedList, CountDownLatch。
: 假设没有 synchronizedList 和 CountDownLatch,
: 就需要自己维护加锁的数据结构和变量。
:
: ===== =====
:
: public class Main {
: public static void main(String[] args) throws Exception{
: System.out.println("run!");
: List<String> results = Collections.synchronizedList(new ArrayList<>());
: ExecutorService es = Executors.newFixedThreadPool(10);
: List<Future<List<String>>> futures = new ArrayList<>();
: for ( int i = 0; i < 5; i++)
: {
: Callable<List<String>> songThread = new SongCrawler();
: Future<List<String>> future = es.submit(songThread);
: futures.add(future);
: }
: for(Future<List<String>> future : futures) {
: List<String> result = future.get();
: results.addAll(result);
: }
: System.out.println(results.size());
: es.shutdown();
: }
: }
:
: ===== =====
:
: 为什么我从来没有用到Fork/Join框架?
:
: 因为多线程的问题 有的是IO密集型的 有的是CPU密集型的(计算密集型)
: 码农碰到的都是IO密集型的问题
: 科学家碰到的是CPU计算密集型的问题
: IO密集型的情况,大多数线程是空闲的。
: 计算密集型的情况,每个CPU内核线程使用一个线程。
: 而Fork/Join框架是为解决后者存在的,所以码农从来没用到过Fork/Join框架。
: --
: ※ 修改:·PlutoKey 于 Dec 6 19:14:11 2021 修改本文·[FROM: 223.104.68.*]
: ※ 来源:·水木社区
http://www.mysmth.net·[FROM: 223.104.68.*]
--
修改:PlutoKey FROM 223.104.68.*
FROM 73.15.185.*