黑马程序员技术交流社区

标题: 关于java1.5新特性Executors [打印本页]

作者: 王浩龙    时间: 2014-3-12 21:08
标题: 关于java1.5新特性Executors
本帖最后由 王浩龙 于 2014-3-15 17:28 编辑

看张老师的java面试题中有关于java1.5新特性Executors和线程池的概念,请问在那里可以看到详细的解释?
谁能解释一下这个新特性的用法就太感谢了

作者: 韩基鑫    时间: 2014-3-12 21:16
http://blog.163.com/allier0000@126/blog/static/33745523201261754514316/去看看吧,希望对你有用
作者: 何伟超    时间: 2014-3-13 12:36

原子操作

如利用AtomicInteger类来解决多线程访问整数类的问题。
Jdk1.5之前Java语言是靠synchronized关键字保证同步的
锁机制存在以下问题:
1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
2)一个线程持有锁会导致其它所有需要此锁的线程挂起。
3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。
synchronized就是一种独占锁,独占锁是一种悲观锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁.,这样工作效率会受影响,从jdk1.5开始,Java提供原子操作的Integer的类。在Java语言中,++ii++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

线程并发库,线程池-------Executors类。

public static void main(String[] args) {

//创建既定大小的缓冲池。

// ExecutorService threadPool = Executors.newFixedThreadPool(3);

//创建一个缓冲线程池,按照线程的数量来决定缓冲池的大小。

ExecutorService threadPool = Executors.newCachedThreadPool();

//创建一个单线程的缓冲池,始终保持该线程池中有一个线程,如果当前线程结束,那么该方法会再创建一个线程来接替前一个线程。

// ExecutorService threadPool = Executors.newSingleThreadExecutor();

for(int i=1;i<=12;i++){

final int task = i;

threadPool.execute(new Runnable(){

// static{

// System.out.println("task is committed!");

// }

@Override

public void run() {

for(int j=1;j<=5;j++){

try {

Thread.sleep(20);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for  task of " + task);

}

}

});

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("all of 10 tasks have committed! ");

// threadPool.shutdown();

//threadPool.shutdownNow();

//

// Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {

// @Override

// public void run() {

// System.out.println("bombing!");

// }

file:///C:/Users/dell/AppData/Local/Temp/ksohtml/wps_clip_image-3526.png// }, 6, 2, TimeUnit.SECONDS);

file:///C:/Users/dell/AppData/Local/Temp/ksohtml/wps_clip_image-6042.png

Executors.newScheduledThreadPool(2).schedule(new Runnable(){

@Override

public void run() {

System.out.println("baozha!");

}

}, 3, TimeUnit.SECONDS);

}

----------用线程池启动定时器

file:///C:/Users/dell/AppData/Local/Temp/ksohtml/wps_clip_image-11656.png

调用ScheduledExecutorService的schedule方法,返回的ScheduleFuture对象可以取消任务。

支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式。

-----(来自JDK)以下是一个带方法的类,它设置了 ScheduledExecutorService ,在 1 小时内每 10 秒钟蜂鸣一次:

import static java.util.concurrent.TimeUnit.*;
class BeeperControl {
    private final ScheduledExecutorService scheduler =
       Executors.newScheduledThreadPool(1);
    public void beepForAnHour() {
        final Runnable beeper = new Runnable() {
                public void run() { System.out.println("beep"); }
            };
        final ScheduledFuture<?> beeperHandle =
            scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
        scheduler.schedule(new Runnable() {
                public void run() { beeperHandle.cancel(true); }
            }, 60 * 60, SECONDS);
    }
}



作者: 何伟超    时间: 2014-3-13 12:38

----------Callable&Future---------

Callable Runnable接口的区别:

Callable 定义的方法是call,Runnable定义的方法是run。
Callable的call方法可以有返回值,而Rannable的run方法不能有返回值。
Callable的call方法可以抛出异常,而Rannable的run方法不能抛出异常

Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果

FutureTask 类是 Future 的一个实现,Future 可实现 Runnable,所以可通过 Executor 来执行。FutureTask 属于代理类 ,负责启动Callable对象,并且可以通过它来获得Callable的返回信息。

FutureTask<String> future =  new FutureTask<String>( new Callable<String>() {

         public String call() {

          return searcher.search(target);

          }

});      

executor.execute(future);

----------------

public class CallableAndFuture {

public static void main(String[] args) {

ExecutorService threadPool =  Executors.newSingleThreadExecutor();

Future<String> future =

threadPool.submit(

new Callable<String>() {

public String call() throws Exception {

Thread.sleep(2000);

return "hello";

};

}

);

System.out.println("等待结果");

try {

System.out.println("拿到结果:" + future.get());

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//提交一组任务用CompletionService

ExecutorService threadPool2 =  Executors.newFixedThreadPool(14);

CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);

//处理返回的feinull的每个结果。

//void solve(Executor e, Collection<Callable<Result>> solvers)throws InterruptedException, ExecutionException {

//         CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);

//         for (Callable<Result> s : solvers)

//             ecs.submit(s);

//         int n = solvers.size();

//         for (int i = 0; i < n; ++i) {

//             Result r = ecs.take().get();

//             if (r != null)

//                 use(r);

//         }

// }

//使用第一个返回的非null的且不抛异常的结果,并在接受到结果之后就取消其他任务。

//     void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {

//              CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);

//              int n = solvers.size();

//              List<Future<Result>> futures = new ArrayList<Future<Result>>(n);

//              Result result = null;

//              try {

//                  for (Callable<Result> s : solvers)

//                      futures.add(ecs.submit(s));

//                  for (int i = 0; i < n; ++i) {

//                      try {

//                          Result r = ecs.take().get();

//                          if (r != null) {

//                              result = r;

//                              break;

//                          }

//                      } catch(ExecutionException ignore) {}

//                  }

//              }

//              finally {

//                  for (Future<Result> f : futures)

//                      f.cancel(true);

//              }

//

//              if (result != null)

//                  use(result);

//    }

for(int i=1;i<=10;i++){

final int seq = i;

completionService.submit(new Callable<Integer>() {

@Override

public Integer call() throws Exception {

Thread.sleep(new Random().nextInt(5000));

return seq;

}

});

}




作者: 何伟超    时间: 2014-3-13 12:45
//提交了10个任务,按照完成顺序拿十次,先完成的先取出。
for(int i=0;i<10;i++){
try {
System.out.println(
completionService.take().get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(2000);
System.out.println("shutdown!");
threadPool.shutdown();
// System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建一个线程池,来执行一组任务
ExecutorService threadPool3 = Executors.newFixedThreadPool(2);
Future<String> future1 = threadPool3.submit(new Callable<String>(){
@Override
public String call() throws Exception {
return "gaomh";
}
});
try {
System.out.println(future1.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CompletionService<String> completionService2 = new ExecutorCompletionService<String>(threadPool3);
for(int i=1;i<=10;i++){
final int task = i;
completionService2.submit(new Callable<String>(){
@Override
public String call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return task+" "+Thread.currentThread().getName();
}
});
}
try {
for(int i = 0;i<10;i++){
System.out.println(completionService2.take().get()+"e");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
-----一个面试题,hibernate中的
User user = session.load(id,User.class);
User user = session.get(id.User.class);有什么区别?
Load是无论用户是否为空,先返回一个User对象的代理,而用到的时候再去数据库查询,如果对象不存在,则抛异常。
Get是直接去数据库中取对象,如果对象为空则返回空,否则返回该对象。
作者: 75100313    时间: 2014-3-13 15:17
:victory:版主 你太虎了 !




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