来自 Web前端 2019-12-21 22:00 的文章
当前位置: 澳门三合彩票 > Web前端 > 正文

几个职务并发推行,三个进程包括三个线程

澳门三合彩票 1

线程 & 线程池

  • 什么是线程?

提到线程,不得不提进程。进程是操作系统的最小资源单位,一个进程能使用多少虚拟内存,能打开多少文件标识符。线程是操作系统的最小调度单元,每个进程默认有一个主线程,它用来执行真正的任务。

  • 在什么情况下,需要使用线程?

多个任务并发执行,提高 CPU 利用率,响应速度,执行效率。例如:主线程负责接收请求,工作线程负责处理请求。

  • 在什么情况下使用线程池?

当你需要使用多个线程来执行相同类型任务时,你不希望自己来管理线程的创建和销毁,维护任务队列,分配任务,管理定时任务。ok,交给线程池吧,你只需要向线程池提交任务就好了。

一、概念

导读:Java编程中,调度Task、Actor通常采用Executors及ExecutorService。对无状态的任务,通常可以很好的胜任。但对于大量并发的有状态任务,需要使用Actor模型。Kontraktor是一个Java编写的轻量级高效Actor模型实现。可以直接暴露Actor提供TCP服务、WebService或者WebSockets,从JavaScript客户端调用Actor方法,用JavaScript实现Actor并通过Java调用。对无状态小任务单元,Executors可以很好的胜任。比如将计算任务分担到多个CPU上。然而,对于运行中的大任务单元Job调度,Executors只能做到次优。例如Actor或轻量级进程的消息调度。许多Actor框架或类似的并发框架使用Executor service批量调度消息。由于Executor service是上下文不敏感的,因此会将单个Actor/Task消息安排多个线程或CPU处理。这会导致访问Actor、Process或Task状态时经常出现缓存未命中的情况。更糟糕的是,因为每个新的“Runnable”会把先前处理的Task缓存冲掉,所以CPU无法维持缓存的稳定。使用忙循环会带来第二个问题。如果框架使用忙循环读取自己的队列,每个处理线程的CPU负载会升到100%。借助Kontraktor

Java 线程池体系

Java 库提供了一套完整的线程池解决方案,支持多种定制化配置,满足你的需求。java.util.concurrent 库与线程池相关的接口,类的继承关系如下所示:

澳门三合彩票 2Executors

  1.进程:一个具有一定独立功能的程序,关于某些数据集合,一次运行活动。 两点:1、有自己的空间存储数据;2、一个程序。  

2.0,我实现了一种不同的调度机制——使用简单的度量标准测试应用实际需要的CPU资源,再进行水平式扩充。每个Actor会固定分配到一个Workerthread。调度器会定期重新调度Actor,根据信息判断是否需要把它们移动到另一个工作线程。由于算法过于复杂通常会带来更高的运行时开销,实际调度时采用了一种非常简洁的方式:[1]如果消费循环连续处理N个消息没有休息,就认定该线程超载。[2]一旦线程标记为“超载”,只要SUM_QUEUED_MSG大于SUM_QUEUED_MSG,信箱中消息最多的Actor会移动到新的线程。[3]如果#Threads

ThreadMax,Actor会根据目前收到的消息和“超载”信息重新分配。问题:如果处理消息的时间差别很大,对消息队列的统计会产生误导。一种改进是为每个消息根据定期分析设定加权。可以简单地用每个Actor加权乘以队列大小。对爆发式负载会有延时,延迟结束后所有可用的CPU才能被真正地使用。JIT真正起效前会有延迟,这会导致错误的分析数据,从而将错误放大。性能为了对比自动化调度与Actor线程固定方式的开销,我运行了Computing-Pi测试。这些数据并没有展示局部性带来的影响,只对固定方式与自动化调度进行了比较。测试1 手动为每个Pi计算Actor分配一个线程,测试2 一旦监测到实际的负载,总起启动一个worker并且自动进行比例调整。该测试运行了8次,每次运行会都会增加thread_max。测试结果:Kontraktor Autoscale

1 threads : 15272 threads : 12733 threads : 7184 threads : 6305 threads : 5216 threads : 5767 threads : 6198 threads : 668

Kontraktor为每个Actor指定固定个数的线程

1 threads : 15202 threads : 8043 threads : 5714 threads : 4595 threads : 4576 threads : 5347 threads : 6158 threads : 659

结论运行结果的区别很大程度上可归结与比例调整带来的延迟。对负载明确的情况,预先安排的Actor调度会更有效率。然而,考虑到服务器收到的请求会不断变化,自动化地调度是一种高效的选择。将Executors/FJ与上面的调度策略进行对比,测试它们各自的缓存效果是很有意思的。不幸的是,Kontraktor不具备基于ExecutorService的消息分发,也没有针对Akka的调度策略实现。此外,还需要一个示例Actors管理私有状态才可以观察缓存效果。

Executor

支持提交任务

voidexecute(Runnablecommand) #提交 Runnable 任务

   进程,是系统   进行   资源分配  和 调度  的基础单位。动态性,独立性,并发性,异步性,结构特征(程序、数据、进程控制块)

ExecutorService

继承 Executor,支持提交异步任务和关闭线程池。

<T>Future<T>submit(Runnabletask, Tresult)Future<?>submit(Runnabletask)void shutdown()

   进程控制块,为  管理进程  而设置的数据结构,用于描述进程过程或者进程状态的变化过程。包括:程序计数器(指令地址)、CPU暂存器(累加器、堆栈指针)等等

ScheduledExecutorService

继承 ExecutorService, 增加支持定时任务和延迟任务

ScheduledFuture<?> schedule( Runnable command, long delay, TimeUnit unit)<V> ScheduledFuture<V> schedule( Callable<V> callable, long delay, TimeUnit unit)ScheduledFuture<?> scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit)ScheduledFuture<?> scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit)

 2. 线程:程序执行的最小单位;单一顺序控制流程;

ThreadPoolExecutor

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

实现 ExecutorService 接口功能外,提供了以下几个配置项:

  • 线程池大小

corePoolSize 线程池保留线程个数,maximumPoolSize 线程池最大线程个数。默认情况下,当提交任务时,才会创建线程。当提交任务时,如果当前 running 线程数小于 corePoolSize 的话,则创建一个线程;如果当前 running 线程数大于 corePoolSize 小于 maximumPoolSize 的话,当且仅当任务队列满的情况下,才会创建一个线程;

  • 线程工厂(threadFactory, 用来创建线程)

默认情况下,使用 Executors.defaultThreadFactory 来创建线程,它们同属于一个线程组,有相同的优先级,non-daemon 状态。

  • 线程空闲多久销毁(keepAliveTime)

当线程个数超过 corePoolSize 之后,如果有线程空闲时间超过 keepAliveTime 的话,线程池就会释放该线程。

  • 任务队列(workQueue)

用来保存未提交和已提交的任务。任务队列的使用情况与线程池内部线程个数有关,如果线程个数小于 corePoolSize 的话,则不会缓存任务,而是创建线程执行任务;如果线程个数大于 corePoolSize 的话,则先缓存任务;如果队列满了,如果线程个数小于 maximumPoolSize 的话,则创建新线程;否则拒绝该任务。目前提供 3 种队列:Direct handoffs Unbounded queues 默认 Bounded queues。详细参考:ThreadPoolExector

  • 当任务队列满了之后的处理策略

ThreadPoolExecutor.AbortPolicy 抛出异常 RejectedExecutionExceptionThreadPoolExecutor.DiscardPolicy 直接丢掉ThreadPoolExecutor.DiscardOldestPolicy 丢掉队列中最老的任务

  通常,一个进程包含多个线程,进程:资源分配,线程:独立运行、独立调度;

澳门三合彩票,ScheduledThreadPoolExecutor

继承 ThreadPoolExecutor,并实现 ScheduledExecutorService 接口行为。

 二、状态

ThreadFactory

接口,定义创建线程

Thread newThread(Runnable r)
  1. 新建状态(New):新创建了一个线程对象。

Executors

用来创建 ExecutorService, ScheduledExecutorService, ThreadFactory, Callable。

public static <T> Callable<T> callable( Runnable task, T result)public static ThreadFactory defaultThreadFactory()public static ExecutorService newCachedThreadPool( ThreadFactory threadFactory)public static ExecutorService newFixedThreadPool( int nThreads, ThreadFactory threadFactory)
  • 使用 Executors 工具类创建 ThreadPoolExecutor
Executors.newFixedThreadPool;Executors.newScheduledThreadPool;
  • 自定义 ThreadFactory,定义 Thread 的名称和设置 Thread 的 daemon 状态。
new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = Executors .defaultThreadFactory() .newThread; t.setName; t.setDaemon; return t; }}
  • 可以设置有固定大小的队列

遗憾的是,Executors 并没有提供支持定制化队列的接口,所以只能使用 ThreadPoolExecutor。

BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>;executorService = new ThreadPoolExecutor( n, n, 0L, TimeUnit.MILLISECONDS, queue);
  • 记住优雅的关闭 ThreadPoolExecutor

shutdown 不接受新的任务,保证已经接受的任务提交执行,但是并不保证任务执行结束awaitTermination 保证已经执行的任务完整执行结束。shutdownNow 关闭正在执行的任务,但不保证正在执行的任务正常关闭。未执行的任务直接返回。

cxnResetExecutor.shutdown();try { if (cxnResetExecutor.awaitTermination( 5, TimeUnit.SECONDS)) { cxnResetExecutor.shutdownNow(); }} catch (Exception ex) { logger.error("Interrupted while waiting for connection reset executor " + "to shut down");}
  • 监控 ThreadPoolExecutor 状态
public long getCompletedTaskCount() #获取已经完成的 task 总个数public int getActiveCount() #获取正在活的线程个数public int getLargestPoolSize() #获取线程池曾经最大的线程数public BlockingQueue<Runnable> getQueue() #获取任务队列中任务个数

ExecutorsExecutorThreadPoolExecutorExecutorService-10个要诀和技巧flume 源码Java线程池分析

欢迎大家访问本人网站 程序员工具箱 致力于贡献便捷的工具,帮助程序员写出更优秀的代码,同时也欢迎大家一起来贡献。

2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

  1. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

 

澳门三合彩票 3

sleep与wait的区别

1、所属类:sleep是thread的方法;wait是Object的方法;

2、锁释放:sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法;

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常;

本文由澳门三合彩票发布于Web前端,转载请注明出处:几个职务并发推行,三个进程包括三个线程

关键词: