当前位置:网站首页>[high concurrency] deeply analyze the callable interface
[high concurrency] deeply analyze the callable interface
2022-06-29 04:45:00 【glacier】
Hello everyone , I'm glacier ~~
This article is pure dry goods , In depth analysis from the perspective of source code Callable Interface , I hope you will step down , Open your IDE, Follow the article to see the source code , I believe you will gain a lot .
1.Callable The interface is introduced
Callable Interface is JDK1.5 New generic interface , stay JDK1.8 in , Declared as a functional interface , As shown below .
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
stay JDK 1.8 Only one method's interface is declared as a functional interface in , Functional interfaces can be used @FunctionalInterface To modify , You can also not use @FunctionalInterface To modify . As long as an interface contains only one method , that , This interface is a functional interface .
stay JDK in , Realization Callable The subclass of the interface is shown in the figure below .

The default subclass hierarchy diagram is not clear , here , Can pass IDEA Right click Callable Interface , choice “Layout” To specify the Callable Interface implementation, different structure of class diagram , As shown below .

here , You can choose “Organic Layout” Options , After selection Callable The structure of subclasses of interfaces is shown in the figure below .

In the realization of Callable In subclasses of interfaces , There are several important classes , As shown in the figure below .

Namely :Executors Static inner class in class :PrivilegedCallable、PrivilegedCallableUsingCurrentClassLoader、RunnableAdapter and Task Under class TaskCallable.
2. Realization Callable Analysis of important classes of interfaces
Next , The main classes analyzed are :PrivilegedCallable、PrivilegedCallableUsingCurrentClassLoader、RunnableAdapter and Task Under class TaskCallable. Although these classes are rarely used directly in practical work , But as a qualified Development Engineer , The setting is for baldness senior experts , Understanding and mastering the implementation of these classes will help you further understand Callable Interface , And improve professional skills ( Another batch of hair loss , Whoahaha ...).
PrivilegedCallable
PrivilegedCallable Class is Callable A special implementation class for interfaces , It shows that Callable Objects have certain privileges to access certain resources of the system ,PrivilegedCallable The source code for the class is as follows .
/**
* A callable that runs under established access control settings
*/
static final class PrivilegedCallable<T> implements Callable<T> {
private final Callable<T> task;
private final AccessControlContext acc;
PrivilegedCallable(Callable<T> task) {
this.task = task;
this.acc = AccessController.getContext();
}
public T call() throws Exception {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<T>() {
public T run() throws Exception {
return task.call();
}
}, acc);
} catch (PrivilegedActionException e) {
throw e.getException();
}
}
}
from PrivilegedCallable Class source code , Can be PrivilegedCallable See it as right Callable Interface encapsulation , And this class also inherits Callable Interface .
stay PrivilegedCallable Class has two member variables , Namely Callable The instance object of the interface and AccessControlContext class , As shown below .
private final Callable<T> task;
private final AccessControlContext acc;
among ,AccessControlContext Class can be understood as a context class with system resource access decision , Through this class, you can access specific resources of the system . Through the class construction method, we can see that , In instantiation AccessControlContext Class , Just pass it on Callable Object of interface subclass , As shown below .
PrivilegedCallable(Callable<T> task) {
this.task = task;
this.acc = AccessController.getContext();
}
AccessControlContext Class objects are created through AccessController Class getContext() Method acquired , here , see AccessController Class getContext() Method , As shown below .
public static AccessControlContext getContext(){
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
return new AccessControlContext(null, true);
} else {
return acc.optimize();
}
}
adopt AccessController Of getContext() The method shows that , First, through getStackAccessControlContext() Method to get AccessControlContext Object instances . If you get AccessControlContext Object instance is empty , By calling AccessControlContext Class constructor instantiation , otherwise , call AccessControlContext Object instance optimize() Method returns AccessControlContext Object instances .
here , Let's take a look first getStackAccessControlContext() What the hell is the method .
private static native AccessControlContext getStackAccessControlContext();
It turned out to be a local method , Method literally means to get the decision context object that can access the system stack .
Next , We go back to PrivilegedCallable Class call() Method , As shown below .
public T call() throws Exception {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<T>() {
public T run() throws Exception {
return task.call();
}
}, acc);
} catch (PrivilegedActionException e) {
throw e.getException();
}
}
By calling AccessController.doPrivileged() Method , Pass on PrivilegedExceptionAction. Interface objects and AccessControlContext object , And finally returns the generic instance object .
First , look down AccessController.doPrivileged() Method , As shown below .
@CallerSensitive
public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action,
AccessControlContext context)
throws PrivilegedActionException;
You can see , Another local approach . in other words , The final implementation will be PrivilegedExceptionAction Interface objects and AccessControlContext Object instance is passed to the local method execution . And in PrivilegedExceptionAction Of the interface object run() Call in method Callable Interface call() Method to execute the final business logic , And return the generic object .
PrivilegedCallableUsingCurrentClassLoader
This class is represented as running under the specific access control that has been established and the current class loader Callable class , The source code is as follows .
/**
* A callable that runs under established access control settings and
* current ClassLoader
*/
static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
private final Callable<T> task;
private final AccessControlContext acc;
private final ClassLoader ccl;
PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
this.task = task;
this.acc = AccessController.getContext();
this.ccl = Thread.currentThread().getContextClassLoader();
}
public T call() throws Exception {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<T>() {
public T run() throws Exception {
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
if (ccl == cl) {
return task.call();
} else {
t.setContextClassLoader(ccl);
try {
return task.call();
} finally {
t.setContextClassLoader(cl);
}
}
}
}, acc);
} catch (PrivilegedActionException e) {
throw e.getException();
}
}
}
This class is easy to understand , First , Three member variables are defined in the class , As shown below .
private final Callable<T> task;
private final AccessControlContext acc;
private final ClassLoader ccl;
Next , Injected by constructor Callable object , In the constructor , First, get the instance of the system security manager object , Check whether there is access through the system security manager object instance ClassLoader And set up ContextClassLoader Authority . And assign values to three member variables in the construction method , As shown below .
PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
this.task = task;
this.acc = AccessController.getContext();
this.ccl = Thread.currentThread().getContextClassLoader();
}
Next , By calling call() Methods to perform specific business logic , As shown below .
public T call() throws Exception {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<T>() {
public T run() throws Exception {
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
if (ccl == cl) {
return task.call();
} else {
t.setContextClassLoader(ccl);
try {
return task.call();
} finally {
t.setContextClassLoader(cl);
}
}
}
}, acc);
} catch (PrivilegedActionException e) {
throw e.getException();
}
}
stay call() Method is also called AccessController Class doPrivileged, Pass on PrivilegedExceptionAction The instance object of the interface and AccessControlContext Object instance of class .
The specific execution logic is : stay PrivilegedExceptionAction Object's run() Method ContextClassLoader object , If you get in the constructor ClassLoader Object is the same as ContextClassLoader Objects are the same object ( Not just object instances , And the memory address is the same ), Call directly Callable Object's call() Method returns the result . otherwise , take PrivilegedExceptionAction Object's run() Method of the current thread ContextClassLoader Set to the class loader object obtained in the constructor , Next , Call again Callable Object's call() Method returns the result . Finally, the current thread's ContextClassLoader Reset to the previous ContextClassLoader.
RunnableAdapter
RunnableAdapter Class is simpler , Given the tasks and results to run , Run the given task and return the given result , The source code is as follows .
/**
* A callable that runs given task and returns given result
*/
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
TaskCallable
TaskCallable Class is javafx.concurrent.Task Static inner class of class ,TaskCallable Class mainly implements Callable Interface and is defined as FutureTask Class , And in this class we are allowed to intercept call() Method to update task The status of the task . The source code is as follows .
private static final class TaskCallable<V> implements Callable<V> {
private Task<V> task;
private TaskCallable() { }
@Override
public V call() throws Exception {
task.started = true;
task.runLater(() -> {
task.setState(State.SCHEDULED);
task.setState(State.RUNNING);
});
try {
final V result = task.call();
if (!task.isCancelled()) {
task.runLater(() -> {
task.updateValue(result);
task.setState(State.SUCCEEDED);
});
return result;
} else {
return null;
}
} catch (final Throwable th) {
task.runLater(() -> {
task._setException(th);
task.setState(State.FAILED);
});
if (th instanceof Exception) {
throw (Exception) th;
} else {
throw new Exception(th);
}
}
}
}
from TaskCallable The source code of the class shows that , Only one... Is defined Task A member variable of type . The main analysis is as follows TaskCallable Class call() Method .
When the execution of the program enters call() When the method is used , First of all, will task Object's started Property is set to true, The task has begun , And set the state of the task to State.SCHEDULED and State.RUNNING, Trigger the scheduling event and the running event of the task in turn . As shown below .
task.started = true;
task.runLater(() -> {
task.setState(State.SCHEDULED);
task.setState(State.RUNNING);
});
Next , stay try Code block Task Object's call() Method , Returns a generic object . If the mission is not cancelled , Then update the task's cache , Will call call() Method returns a generic object bound to Task Object ObjectProperty
private final ObjectProperty<V> value = new SimpleObjectProperty<>(this, "value");
Next , Set the status of the task to success . As shown below .
try {
final V result = task.call();
if (!task.isCancelled()) {
task.runLater(() -> {
task.updateValue(result);
task.setState(State.SUCCEEDED);
});
return result;
} else {
return null;
}
}
If the program throws an exception or error , Will enter catch() Code block , Set up Task Object's Exception And set the status to State.FAILED, That is to mark the task as failed . Next , Determine the type of exception or error , If it is Exception Exception of type , Then it will be changed into Exception Type and throw . otherwise , Encapsulate an exception or error as Exception Object and throw , As shown below .
catch (final Throwable th) {
task.runLater(() -> {
task._setException(th);
task.setState(State.FAILED);
});
if (th instanceof Exception) {
throw (Exception) th;
} else {
throw new Exception(th);
}
}
remember : Where you are better than others , It's not how many years you've been doing it CRUD Work , It's that you have more in-depth skills than others . Don't stay on the road all the time CRUD The surface work of , Understand and master the underlying principles and familiar with the source code implementation , And form their own abstract thinking ability , Flexible use , It's you who break through the bottleneck , The important direction to stand out !
Last , As a qualified ( The hairline is relatively high ) Developer or senior ( Baldness ) For engineers and architects , Understand the principle and master the source code , And form their own abstract thinking ability , Flexibility is a skill you must master .
Okay , That's all for today , I'm glacier , See you next time ~~
边栏推荐
- 开启生态新姿势 | 使用 WordPress 远程附件存储到 COS
- Flyweight pattern
- 直播预约|AWS Data Everywhere 系列活动
- What exactly does GCC's -Wpsabi option do? What are the implications of supressing it?
- 软件体系结构实验汇总
- What are the ways to simulate and burn programs? (including common tools and usage)
- JVM memory tuning method
- Hantai oscilloscope software | Hantai oscilloscope upper computer software ns-scope, add measurement data arbitrarily
- How to test electronic components with a multimeter
- How to write MySQL scheduled backup script in Linux
猜你喜欢

The 30th day of force deduction (DP topic)

Alibaba microservice component Sentinel

Mysql 中的 mvcc原理

Notebook access desktop shared disk

JDBC learning

基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能

What are the ways to simulate and burn programs? (including common tools and usage)

如何用万用表测试电子部件

Mediator pattern

安捷伦数字万用表软件NS-Multimeter,实时数据采集数据自动保存
随机推荐
Microsoft Pinyin IME personal preferences
What is the method of connection query in MySQL
CTO and programmer were both sentenced because the crawler was out of control!
直播预约|AWS Data Everywhere 系列活动
【HackTheBox】dancing(SMB)
Talking about Canary deployment
【HackTheBox】dancing(SMB)
Research Report on the overall scale, major manufacturers, major regions, products and applications of high temperature film capacitors in the global market in 2022
How to write MySQL scheduled backup script in Linux
【代码随想录-哈希表】T15、三数之和-双指针+排序
[code Capriccio - dynamic planning] longest common subsequence
1016 part a+b
Network device setting / canceling console port login separate password
Alibaba microservice component Sentinel
Research Report on the overall scale, major manufacturers, major regions, products and application segments of semiconductor wafer metal stripping platform in the global market in 2022
仿真与烧录程序有哪几种方式?(包含常用工具与使用方式)
Technical parameters of Tektronix DPO4104 digital fluorescence oscilloscope
开启生态新姿势 | 使用 WordPress 远程附件存储到 COS
Quelles sont les méthodes de simulation et de gravure des programmes? (comprend les outils communs et la façon dont ils sont utilisés)
[hackthebox] dancing (SMB)