Java并发1

P655)静态方法Thread.yield()的调用是对线程调度器(Java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议:此线程以及执行完生命周期中最重要的部分了,此刻正是切换给其他任务执行一段时间的大好时机。P661)不过这只是一个暗示,没有任何机制保证它将会被采纳。当调用yield()时,你也是在建议具有相同优先级的其他线程可以运行。实际上,对于任何重要的控制或在调整应用时,都不能依赖yield()。

 

P656)Executor允许你管理异步任务的执行,而无须显式的管理线程的生命周期。ExecutorService(具有服务生命周期的Executor???,例如关闭)知道如何构建恰当的上下文来执行Runnable对象。ExecutorService对象是使用静态的Executor方法创建的。对shutdown()方法的调用可以防止新任务被提交给这个Executor,当前进程将继续运行在shutdown()被调用之前的所有任务。这个程序将在Executor中的所有任务完成之后尽快退出。

 1 public class CachedThreadPool {
 2     public static void main(String[] args){
 3         ExecutorService exec = Executors.newCachedThreadPool();
 4         for(int i = 0; i < 5; i++){
 5             exec.execute(new LiftOff());
 6         }
 7         exec.shutdown();
 8     }
 9 
10     static class LiftOff implements Runnable{
11         protected int countDown = 10;
12         private static int taskCount = 0;
13         private final int id = taskCount++;
14         private final int nextRow = 5;
15 
16         public LiftOff(){}
17 
18         public LiftOff(int countDown){
19             this.countDown = countDown;
20         }
21 
22         public String status(){
23             return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + "), ";
24         }
25 
26         @Override
27         public void run() {
28             while(countDown-- > 0){
29                 if(countDown == nextRow)
30                     System.out.println();
31                 System.out.print(status());
32                 Thread.yield();
33             }
34         }
35     }
36 }

P657)FixedThreadPool

有了FixThreadPool,你可以一次性预先执行代价高昂的线层分配,因而也就可以限制线程的数量了。这可以节省时间,因为你不用为每个任务都固定的付出创建线程的开销。在事件驱动的系统中,需要线程的事件处理器,通过直接从池中获取线程,也可以如你所愿的尽快得到服务。你不会滥用可获得的资源,因为FixThreadPool使用的Thread对象数量是有界限的。

 

CacheThreadPool

CacheThreadPool在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是合理的Executor的首选。只有当这种方式会引起问题时,你才需要切换到FixedThreadPool。

 

SingleThreadPool

SingleThreadPool就像是线程数量为1的FixedThreadPool。这对于你希望在另一个线程中连续运行任何事物(长期存活的任务)来说,都是很有用的。如果向SingleThreadPool提交了多个任务,那么这些任务将排队,每个任务都会在下一个任务开始之前结束,所有的任务将使用相同的线程。SingleThreadPool会序列化所有提交给它的任务,并且维护它自己(隐藏)的悬挂任务队列。

 

P658)Callable

如果希望任务在完成时能够返回一个值,那么可以实现Callable接口而不是Runnable接口,并且必须使用ExecutorService.submit()方法调用它。submit()方法会产生Future对象。你可以用isDone()方法来查询Future是否已经完成,你也可以不用isDone()进行检查就直接调用get(),在这种情况下,get()将阻塞,知道结果准备就绪。你也可以调用具有超时的get()。

 

P659)休眠

1 // Old-style:
2 // Thread.sleep(100);
3 // Java SE5/6-style
4 TimeUnit.MILLISECONDS.sleep(100);

 

通过调用Thread.currentThread()来获得对驱动该任务的Thread对象的引用。setPriority(int)来设置线程优先级。注意,优先级是在run()的开头部分设定的,在构造器中设置它们不会有任何好处,因为Executor在此刻还没有开始执行任务。

 

尽管JDK有10个优先级,但它与多数操作系统都不能映射得很好。唯一可移植的方法是当调整优先级时,只使用MAX_PRIORITY、NORM_PRIORITY和MIN_PRIORITY三种级别。

posted @ 2017-06-27 19:58  TooLateToLearn!  阅读(222)  评论(0编辑  收藏  举报