- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
阻塞队列在 Android 中有很多应用,比如:
阻塞队列支持两个核心方法,分别为:
在 Java 中,阻塞队列的实现类有 ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue 等等。这些队列通过使用 Lock 和 Condition 来保证队列的线程安全.
是当阻塞队列中没有数据的时候,读线程将被阻塞;当阻塞队列已满的时候,写线程将被阻塞。阻塞队列通过内部锁来控制读和写操作的相互访问以及有序性,保证在多线程并发的时候,执行插入或读取操作是广泛可接受的,而不会引起任何问题.
线程池是维护一个工作线程的线程容器,用于优化线程的创建和销毁带来的开销。下面简单介绍一下线程池的底层实现原理.
ThreadPoolExecutor
构造函数赋值并创建核心线程池; execute()
方法将任务存放到阻塞队列中,如果有空闲线程,则取出最先进入队列的任务开始执行,否则加入等待中的队列中; 以下是线程池最基本的四类参数.
核心线程数(corePoolSize):线程池中的基本线程数。当任务提交后,分类讨论:
最大线程数(maximumPoolSize):线程池中允许存在的最大线程数。当缓冲队列满时,对于大于 corePoolSize 的任务将会此项启动更多的 Thread 来处理用户请求,针对有界和无界不同表现。如有等待队列功能满了后会执行 RejectedExecutionException 。在我看来这个配置很鸡肋,往往在它小于 corepoolsize 时候有表现,大于情况视大于多少对线程池复用机制上友好而已。有不对的欢迎评论区讨论下; 。
队列容量(workQueue):等待任务的队列容量。在调用 execute() 方法时,阻塞队列可以用以下三种类型之一:
空闲线程销毁时间(keepAliveTime):线程池中没有任务执行时,即空闲状态下的线程没事可做,这些空闲的线程会自动的销毁,首先由coreThreadHandle(正常获得锁的线程)完成剩下工作,然后 wait coreHandle 释放锁资源,休眠到内部队列不为空或超时返回,如果休眠超时则表示该线程超时了,在低于 corePoolSize 的情况下 除非设置allowCoreThreadTimout=true,否则永远不会发生; 。
public class TestThreadPoll implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行...");
}
}
public static void main(String[] args) {
// 创建一个基本的线程池
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
Runnable task = new TestThreadPoll();
executor.execute(task);
}
executor.shutdown();
}
上面的创建了一个基本的线程池,并进行了线程数的添加.
当线程池中所有的线程都在执行任务时,如果新提交的任务需要被执行,那么这个新的任务会进入到一个阻塞队列中排队等待。而ThreadPoolExecutor中有四种常见的阻塞队列:SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue.
其中SynchronousQueue是没有任何储存功能的阻塞队列,它只负责一个任务的传递,即前一个任务将后一个任务提交给线程池后直接结束,而不是进入等待队列。由于该队列没有储存空间,所以当一个线程提交任务时,该队列会寻找与之对应的另一个线程来接收这个任务。如果此时线程池处于饱和状态,这个任务就有可能被丢弃.
LinkedBlockingQueue则是一个带储存功能的无界队列,也就是说,这个队列可以一直往里添加新的元素。因此,它的长度限制仅仅是由内存大小来控制,如果你的阻塞队列需要存储非常多的任务,那么最好选用这个类型的阻塞队列.
ArrayBlockingQueue也是一个带储存功能的有界队列,它的长度是预设好的,如果你试图往这个队列中添加超过预设长度的任务,那么新增的任务就必须要等待其他任务完成或者被移除后才能加入队列了,换而言之,在这种队列中,无法满足新任务的请求时会出现阻塞情况.
PriorityBlockingQueue则是一个支持优先级排序的无界队列,也就是说,任务可以通过实现Comparable接口来设置一个队列中的优先级关系。当使用优先级队列时,可以为不同的任务设置不同的优先级,程序会按照任务的优先级顺序执行具体的任务.
以下是一个简单的自实现线程池示例:
public class MyThreadPool {
private final BlockingQueue<Runnable> workQueue;
private final WorkerThread[] workers;
public MyThreadPool(int nThreads) {
this.workQueue = new LinkedBlockingQueue<>();
this.workers = new WorkerThread[nThreads];
for (int i = 0; i < nThreads; i++) {
workers[i] = new WorkerThread();
workers[i].start();
}
}
public void execute(Runnable task) {
synchronized (workQueue) {
workQueue.add(task);
workQueue.notify();
}
}
private class WorkerThread extends Thread {
@Override
public void run() {
while(true) {
Runnable task;
synchronized (workQueue) {
while (workQueue.isEmpty()) {
try {
workQueue.wait();
} catch (InterruptedException e) {
return;
}
}
task = workQueue.poll();
}
try {
task.run();
} catch(Throwable t) {
// error handling code
}
}
}
}
}
这是一个最简单的线程池实现,其核心思想就是:在.WorkerThread类中定义了一个死循环,负责从任务队列中取出任务并执行。如果目前没有任务,则等待新任务到来.
使用时初始化线程池:
MyThreadPool pool = new MyThreadPool(2);
之后将需要做的任务加入线程池中:
pool.execute(new Runnable() {
@Override
public void run() {
// 执行具体的任务代码
}
});
至此,自实现的线程池实例就完成了.
execute() 是Java中Executor接口的一个方法,它在执行传递给它的Runnable任务时使用。Executor框架提供了一种将任务提交给线程池以异步执行的方式。 当我们想要某段代码在异步环境中运行,又不需要知道每个任务何时完成时(所需时间可能会非常不同)的情况下,就可以使用这个框架。该框架管理和复用线程,以避免耗费创建他们的代价,并且在执行完任务后返回线程到线程池。 execute() 方法的目的是在默认池中安排一个任务来执行,由于这个方法只是将任务提交给线程池并立即返回,因此不能保证任务已经执行。这个方法只有在向线程池中添加任务时需要使用,例如对于没有返回值的简单操作或前置条件检查。 以下是 execute() 的方法语法:
void execute(Runnable command);
参数
command
:Runnable对象,该接口定义了需要在线程上执行的任务。 实现: 该方法直接将任务提交给主执行器以异步执行。然后返回而不等待任务的结束。如果需要使用结果,则调用 submit 方法.
//newFixedThreadPool 被重载用来覆盖默认设置,指定核心线程数和最大线程数相同。
//此示例将线程池大小限制为 5 个工作线程。
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new ExampleRunnable("" + i);
executor.execute(worker);
}
// 当所有可执行任务都完成后关闭线程池
executor.shutdown();
// 阻塞当前线程直到关闭操作完成
while (!executor.isTerminated()) { }
System.out.println("Finished all threads");
以上代码中,新的线程池有默认的限制,而不需要明确地声明线程池的大小或能力 .
线程池固定大小,当队列中没有可以在工作线程上执行的任务时(即阻止列表为空),则该任务将继续等待直到可用.
在每个可用工作线程上使用while循环反复启动一个Runnable任务并让其运行到池的关闭标志被设置 。
线程池被关闭之后,isTerminated()方法返回true,并退出while循环.
最后此篇关于ThreadPool实现机制的文章就讲到这里了,如果你想了解更多关于ThreadPool实现机制的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
广播的原则 如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。 在上面的对arr每一列减去列
之前在讲 MySQL 事务隔离性提到过,对于写操作给读操作的影响这种情形下发生的脏读、不可重复读、虚读问题。是通过MVCC 机制来进行解决的,那么MVCC到底是如何实现的,其内部原理是怎样的呢?我们要
我创建了一个 JavaScript 对象来保存用户在 ColorBox 中检查复选框时设置的值。 . 我对 jQuery 和“以正确的方式”编程 JavaScript 比较陌生,希望确保以下用于捕获用
我为了回答aquestion posted here on SO而玩示例,发现很难理解python的import *破坏作用域的机制。 首先是一点上下文:这个问题不涉及实际问题;我很清楚from fo
我想让我的类具有标识此类的参数 ID。例如我想要这样的东西: class Car { public static virtual string ID{get{return "car";}} }
更新:我使用的是 Java 1.6.34,没有机会升级到 Java 7。 我有一个场景,我每分钟只能调用一个方法 80 次。它实际上是由第 3 方编写的服务 API,如果您多次调用它,它会“关闭”(忽
希望这对于那些使用 Javascript 的人来说是一个简单的答案...... 我有一个日志文件,该文件正在被一个脚本监视,该脚本将注销中的新行提供给任何连接的浏览器。一些人评论说,他们希望看到的更多
我们正在开发针对 5.2 开发的 PHP 应用程序,但我们最近迁移到了 PHP 5.3。我们没有时间去解决所有迁移到 PHP 5.3 的问题。具体来说,我们有很多消息: Declaration of
简介 在实现定时调度功能的时候,我们往往会借助于第三方类库来完成,比如: quartz 、 spring schedule 等等。jdk从1.3版本开始,就提供了基于 timer 的定时调度功能。
Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而
我将编写自己的自定义控件,它与 UIButton 有很大不同。由于差异太大,我决定从头开始编写。所以我所有的子类都是 UIControl。 当我的控件在内部被触摸时,我想以目标操作的方式触发一条消息。
在我的代码中,在创建 TIdIMAP4 连接之前,我设置了一大堆 SASL 机制,希望按照规定的“最好到最差”顺序,如下所示: IMAP.SASLMechanisms.Add.SASL := mIdS
在 Kubernetes 中,假设我们有 3 个 pod,它们物理上托管在节点 X、Y 和 Z 上。当我使用“kubectl expose”将它们公开为服务时,它们都是集群中的节点(除了 X、Y 和
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我知道进程间通信 (ipc) 有几种方法,例如: 文件 信号 socket 消息队列 管道 命名管道 信号量 共享内存 消息传递 内存映射文件 但是我无法找到将这些机制相互比较并指出它们在不同环境中的
当我尝试连接到 teradata 时,出现了TD2 机制不支持单点登录 错误。 在 C# 中,我遇到了类似的问题,我通过添加 connectionStringBuilder.Authetication
我有一个带有 JSON API 的简单 Javascript 应用程序。目前它在客户端运行,但我想将它从客户端移动到服务器。我习惯于学习新平台,但在这种情况下,我的时间非常有限 - 所以我需要找到绝对
我想了解事件绑定(bind)/解除绑定(bind)在浏览器中是如何工作的。具体来说,如果我删除一个已经绑定(bind)了事件的元素,例如使用 jQuery:$("#anElement").remove
我不是在寻找具体答案,只是一个想法或提示。我有以下问题: Android 应用程序是 Web 服务的客户端。它有一个线程,通过 http 协议(protocol)发送事件(带有请求 ID 的 XML
我正在研究 FreeBSD TCP/IP 栈。似乎有 2 种 syn flood 机制,syncookies 和 syncache。我的问题是关于 syncookies,它是从头开始还是在 SYN 队
我是一名优秀的程序员,十分优秀!