首页 > 编程知识 正文

java高并发框架有哪些,java常用并发框架

时间:2023-05-06 03:56:09 阅读:42490 作者:4052

执行框架介绍

Executors框架在内部采用线程池机制,通过在java.util.cocurrent包下控制线程的启动、执行和关闭,简化并发编程操作。 因此,在Executors中启动线程比使用Thread的start方法更好,而且更容易管理和高效。 此外,还有一个重要方面,这有助于避免this溢出。

Executors框架包括线程池、Executor、Executors、ExecutorService、CompletionServince、Future和Callable。

执行程序类

Executor接口定义了接受Runable实例的方法execute(Runable )接口,用于执行实现Runable接口的类的任务。

ExecutorService

ExecutorService继承在Executor界面中,提供了更丰富的线程实现方法,包括ExecutorService如何关闭自己,以及如何生成Future以跟踪一个或多个异步任务的执行情况

ExecutorService有三种状态:运行、关闭和退出。 创建后将进入运行状态,调用shutdown ) )方法时将进入关闭状态。 也就是说,ExecutorService不再接受新任务,但它将执行已提交的任务,并在所有已提交的任务都执行后退出。 如果不调用shutdown方法,ExecutorService方法将始终运行,系统通常不会主动关闭。

执行程序

executor提供了用于创建线程池的工厂方法,所有返回的线程池都实现ExecutorService接口。

publicstaticexecutorservicenewfixedthreadpool (intn ) )。

为固定数量的线程创建线程池。

newFixedThreadPool与缓存线程池几乎相同。 如果可以使用reuse,但不能随时创建新线程;

在任何给定时间,只能存在最大固定数量的线程。 此时,如果创建了新线程,则只需将其放入等待队列,它就会在线程池中的某些线程结束并从线程池抛出后进入线程池并运行。

与缓存线程池不同,固定线程池没有IDLE机制,因此固定线程池大多面向稳定的线程开发,并大量用于服务器。

固定线程池与cacheThreadPool类似,使用相同的基础池,但参数不同、固定的fix线程、无IDLE空闲的cache线程为0-Integer.MAX_VALUE

publicstaticexecutorservicenewcachethreadpool (

创建可缓存池并调用execute时,以前构建的线程可用时将被重用。 如果线程不可用,请在线程池中创建线程。 退出并删除线程池中60s以上的未使用线程。

缓存池通常用于执行生存期较短的异步线程任务。

放入cacheThreadPool的线程不必担心退出,超时后会自动退出。

默认值timeout=60s

publicstaticexecutorservicenewsinglethreadexecutor ()

创建单线程执行程序。

使用与cache和fixedhldxx相同的基础池,没有IDLE。

publicstaticscheduleexecutorservicenewschedulethreadpool (intcorepoolsize ) () ) ) ) ) ) 660

创建支持计划和周期性任务执行的线程池。 在大多数情况下,可以代替Timer类。 Timer有以下缺点

无论Timer类启动了多少计时器,它都只启动一个线程,如果有多个计时器任务,则会发生延迟。 例如,一个任务每3S执行一次,执行大约需要10S的时间,第二个任务每5S执行一次,两个任务要求同时启动。 使用Timer,可以看到第一个任务在第一个任务执行完成后5S开始执行。 这就是多任务延迟问题。

如果多个定时任务中有一个任务抛出异常,则无法执行该所有任务。

Timer在执行周期任务时依赖于系统时间。 系统时间发生变化时,Timer的执行结果也可能发生变化。 另一方面,ScheduledExecutorService是基于时间的延迟,不是时间,因此执行不会随着系统时间的变化而变化。 如上所述,定时任务使用ScheduledExecutorService代替Timer。

执行程序

任务分为两类:实现Runable的类和实现Callable的类。 两者都可以在ExecutorService中执行,但Runable任务没有返回值,Callable任务具有返回值。 此外,Callable的Call方法只能在ExecutorService的submit方法中执行,并返回等待任务完成的Future。

>

Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常而Callable又返回结果,而且当获取返回结果时可能会抛出异常。Callable中的call()方法类似Runnable的run()方法,区别同样是有返回值,后者没有。

当将一个Callable的对象传递给ExecutorService的submit方法,则该call方法自动在一个线程上执行,并且会返回执行结果Future对象。同样,将Runnable的对象传递给ExecutorService的submit方法,则该run方法自动在一个线程上执行,并且会返回执行结果Future对象,但是在该Future对象上调用get方法,将返回null。

实例

1 public static void main(String[] args) throwsInterruptedException, ExecutionException {2 ExecutorService executorService=Executors.newCachedThreadPool();3

4 executorService.execute(newRunnable() {5

6 @Override7 public voidrun() {8 //TODO Auto-generated method stub

9

10 }11 });12

13 ExecutorService service=Executors.newCachedThreadPool();14 Future future=service.submit(new Callable() {15 publicString call() {16 return "";17 }18 });19

20 if(future.isDone()) {21 String reString=future.get();22 }23

24 executorService.shutdown();25 service.shutdown();

}

获得Callable的多条数据的方式

自己封装一个Callable 的结果集,但是这个有弊端

使用ExecutorService.invokeAll函数。

使用CompletionService获取,BlockingQueue、LinkBlockingQueue。

1 ExecutorService service=Executors.newFixedThreadPool(10);2

3 ArrayList> list=new ArrayList>();4

5 for(int i=0;i<10;i++) {6 Future rFuture=service.submit(new Callable() {7

8 @Override9 public String call() throwsException {10 int sleepTime=new Random().nextInt(1000);11 Thread.sleep(sleepTime);12 return "线程"+"睡了"+sleepTime+"秒";13 }14 });15 list.add(rFuture);16 }17 for(int i=0;i<10;i++) {18 Future future=list.get(i);19 String reString=future.get();20 System.out.println(reString);21 }22 //这种方式处理Callable所得结果集的弊端

23 /*

24 * 需要自己创建容器,而且维护所有的返回结果,比较麻烦25 * 从list遍历的每个Future并不一定处于完成状态,这时调用get方法会被阻塞住,如果系统是设计成每个线程完成后根据结果继续执行后面的事,这样的26 * 处于list后面的但是先完成的线程会增加无用的时间。27 */

28 ExecutorService executorService=Executors.newFixedThreadPool(10);29 List> list2=new ArrayList>();30 for(int i=0;i<10;i++) {31 Callable task=new Callable() {32 @Override33 public String call() throwsException {34 int sleep=new Random().nextInt(1000);35 Thread.sleep(sleep);36 return "线程"+"睡了"+sleep+"秒";37 }38 };39 executorService.submit(task);40 list2.add(task);41 }42 ArrayList> res=(ArrayList>) executorService.invokeAll(list2);43

44 for(int i=0;i<10;i++) {45 Future future=res.get(i);46 System.out.println(future.get());47 }48 /*

49 * 这个方法避免了1方法的不足50 * CompletionService内部维护了一个阻塞队列,只有执行完成的任务结果才会被放入该队列,这样就确保执行时间较短的任务率先被存入阻塞队列中。51 */

52

53 ExecutorService exe=Executors.newFixedThreadPool(10);54 final BlockingDeque> queue=new LinkedBlockingDeque<>();55 final CompletionService completionService=new ExecutorCompletionService(exe,queue);56

57 for(int i=0;i<10;i++) {58 exe.submit(new Callable() {59

60 @Override61 public String call() throwsException {62 int sleep=new Random().nextInt(1000);63 Thread.sleep(sleep);64 return "线程"+"睡了"+sleep+"秒";65 }66 });67 }68 for(int i=0;i<10;i++) {69 Future future=completionService.take();70 System.out.println(future.get());71 }

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。