总体介绍
浏览器运行是多进程的,包括主进程、渲染进行、网络进程和GPU进程等等
解析HTML时(渲染进程)用到两大引擎,一个是渲染引擎(用于渲染页面)、一个是JS引擎用于解析JS代码。又JS引擎运行是单线程的,所以渲染和 js引擎是互斥的。这就要求提高JS引擎解析时间,防止长时间堵塞主线程,以提高渲染效率。异步就可用来解决此问题。
渲染引擎的线程运行
浏览器运行渲染进程先利用渲染引擎渲染页面,渲染过程如下:
JS引擎的线程运行
主线程中的任务先进入任务队列中给JS引擎解析,其他线程的任务(优先级如下图)的以回调任务进行队列待JS引擎解析。若JS代码改变了DOM树,渲染任务又进入任务队列中待渲染引擎执行。
主线程就监控检查任务队列中是否任务待执行,有就在主线程中执行,部分任务给其他线程运行(异步任务)【这些任务根据逻辑(如定时3s)将回调函数传到任务队列中,待主线程执行】
Java异步
需求与实现:要实现一个可以被多次触发但在前一次任务完成后才触发下一个任务的异步方法,你可以使用队列来存储待执行的任务,并确保只有在前一个任务完成后才执行下一个任务。
异步任务(定义任务):
public class AsyncTask implements Runnable{private final Map<String,Object> requestData;private final CallPy callPy;public AsyncTask(CallPy callPy, Map<String,Object> requestData) {this.requestData = requestData;this.callPy=callPy;}@Overridepublic void run() {// 从requestData中获取数据Methods methods= (Methods) requestData.get("methods");System.out.println("methods:"+methods);Parameters parameters = (Parameters) requestData.get("parameters");// 长时间运行的处理逻辑// 这里可以是调用后端模型的处理过程callPy.execute(methods,parameters);// 处理完成后,将结果存储在某个地方,如数据库或缓存中}
}
异步+队列(实现调用):
public class AsyncQueue {private final Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();private final Executor executor = Executors.newSingleThreadExecutor();private boolean isRunning = false;public synchronized void executeAsyncTask(Runnable task) {// 将任务加入队列taskQueue.add(() -> {try {task.run();} finally {// 任务完成后检查队列并执行下一个任务executeNextTask();}});// 如果当前没有任务在执行,则执行队列中的第一个任务if (!isRunning) {executeNextTask();}}private synchronized void executeNextTask() {// 检查队列是否为空Runnable nextTask = taskQueue.poll();if (nextTask != null) {// 标记当前有任务正在执行isRunning = true;// 使用线程池执行任务CompletableFuture.runAsync(nextTask, executor).thenRunAsync(this::executeNextTask, executor).exceptionally(ex -> {ex.printStackTrace();return null;});} else {// 标记当前没有任务在执行isRunning = false;}}
}
调用处理方法
// 异步处理请求的方法private void asyncProcess(AsyncQueue asyncQueue,Map<String,Object> Data) {// 这里使用异步任务来处理请求
// AsyncQueue asyncQueue=new AsyncQueue();//变了AsyncTask asyncTask = new AsyncTask(callpy,Data);asyncQueue.executeAsyncTask(asyncTask);
// new Thread(asyncTask).start();}