给几个能看的网站 贴吧,怎么注销自己做的网站,wordpress翻页数字,免费无限建站系统在Java中什么是同步#xff1f;什么是异步#xff1f;对于这两个概念我们必须要明确。只有明确这两个概念#xff0c;才会在明确在什么场景下使用同步以及异步。 在这里我可以形象的举个例子来辨明这两个概念#xff1a; 1.同步与异步同步和异步关注的是消息通信机制 (sync… 在Java中什么是同步什么是异步对于这两个概念我们必须要明确。只有明确这两个概念才会在明确在什么场景下使用同步以及异步。 在这里我可以形象的举个例子来辨明这两个概念 1.同步与异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 所谓同步就是在发出一个*调用*时在没有得到结果之前该*调用*就不返回。但是一旦调用返回就得到返回值了。换句话说就是由*调用者*主动等待这个*调用*的结果。 而异步则是相反*调用*在发出之后这个调用就直接返回了所以没有返回结果。换句话说当一个异步过程调用发出后调用者不会立刻得到结果。而是在*调用*发出后*被调用者*通过状态、通知来通知调用者或通过回调函数处理这个调用。 典型的异步编程模型举个通俗的例子你打电话问书店老板有没有《分布式系统》这本书 如果是同步通信机制书店老板会说你稍等”我查一下然后开始查啊查等查好了可能是5秒也可能是一天告诉你结果返回结果。 而异步通信机制书店老板直接告诉你我查一下啊查好了打电话给你然后直接挂电话了不返回结果。然后查好了他会主动打电话给你。 在这里老板通过“回电”这种方式来回调。 2. 阻塞与非阻塞阻塞和非阻塞关注的是程序在等待调用结果消息返回值时的状态.阻塞调用是指调用结果返回之前当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前该调用不会阻塞当前线程。还是上面的例子 你打电话问书店老板有没有《分布式系统》这本书你如果是阻塞式调用你会一直把自己“挂起”直到得到这本书有没有的结果如果是非阻塞式调用你不管老板有没有告诉你你自己先一边去玩了 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。 在开始解决上述问题之前我们来讨论下使用Callbale接口来创建线程。 FunctionalInterface
public interface CallableV {/*** 返回一个任务的结果或者抛出一个异常(如果不能计算结果)*/V call() throws Exception;
} Callable接口是一个函数式接口其中call方法的返回值的类型就是Callable接口的泛型的类型。但是Callable接口怎么和线程扯上关系呢? FutureTask类存在一个构造器如下所示 FutureTask(CallableV callable) 其中的参数正式Callable接口对象FutureTask类又是实现接口RunnableFuture接口 public class FutureTaskV implements RunnableFutureV 接着看 public interface RunnableFutureV extends Runnable, FutureV {void run();
} 最终的还是继承了Runnable接口和Future接口为了说明关系我们画出类图 package com._thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableThread implements CallableString {/*** 票的张数为50张总共100个人买票*/private int ticket 50;// 表示票的张数
Overridepublic String call() throws Exception {for (int i 0; i 100; i) {if (ticket 0) {System.out.println(买票ticket this.ticket--);}}return 票卖光了;}public static void main(String[] args) throws InterruptedException, ExecutionException {// 创建Callable接口对象 在这里我创建了两个任务对象CallableString callable1 new CallableThread();CallableString callable2 new CallableThread();// 将创建的callable任务对象存储在FutureTask对象中FutureTaskString task1new FutureTaskString(callable1);FutureTaskString task2new FutureTaskString(callable2);// 启动线程执行任务new Thread(task1).start();new Thread(task2).start();// 上述代码只是执行线程callable接口是可以产生结果的futuretask可以获取结果// 调用get()方法可以阻止当前执行的线程获取结果System.out.println(线程A的返回结果是:task1.get());System.out.println(线程B的返回结果是:task2.get());}
} 这是使用callable接口来创建线程的一种实现过程好了现在让我们讨论Java异步编程吧 上面的图可以说明我们的一个买书的过程在Java中可以视这个操作为同步操作 package com._thread;public class SlowWorker {public SlowWorker() {}public void doWork() {try {System.out.println( 找书, 找书, 找书 );Thread.sleep(2000);System.out.println( OK! );} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SlowWorker worker new SlowWorker();// 主线程模拟买书的人doWork()方法模拟书店老板的行为System.out.println(老板我要买书 new java.util.Date());worker.doWork();System.out.println(... 老板在找书的过程中我可以干些事情吗....);System.out.println(书买到了 new java.util.Date());System.exit(0);}
} 看运行结果 老板我要买书Sun Jan 21 01:49:35 CST 2018找书, 找书, 找书 OK!
... 老板在找书的过程中我可以干些事情吗....
书买到了Sun Jan 21 01:49:37 CST 2018 以上的操作确实是一种同步的操作主线程运行开始后调用doWork()方法而doWork()方法需要休眠2s.但是主线程没有继续执行而是等待了大家是不是感觉这样做事很没有效率。换言之如果你在书店买书老板找一天你会持续等待下去吗 接下来我们谈谈ExecutorService这个接口它可以表示线程池对象当线程空闲时它可以接受一个提交给ExecutorService的callable对象当线程结束的时候他会返回一个Future. package com._thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;/*** 异步编程* author gosaint**/
public class AsynchronousWorker {public AsynchronousWorker() {}public void doWork() {try {System.out.println( 找书, 找书, 找书 );Thread.sleep(2000);System.out.println( OK! );} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SlowWorker worker new SlowWorker();// 主线程模拟买书的人doWork()方法模拟书店老板的行为System.out.println(老板我要买书 new java.util.Date());// 此时我们创建一个线程池个数为3ExecutorService service Executors.newFixedThreadPool(3);// 此时存在一个线程池对象线程池对象提交任务是一个callable接口FutureString future service.submit(new CallableString() {Overridepublic String call() throws Exception {new AsynchronousWorker().doWork(); return null;}});System.out.println(... 老板在找书的过程中我可以干些事情吗....);System.out.println(做爱做的事情);try {//调用此方法可以获取我们任务的执行结果但是会阻止主线程的运行直到得到一个结果future.get(); } catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}System.out.println(书买到了 new java.util.Date());System.exit(0);}} 运行结果如下 老板我要买书Sun Jan 21 02:16:13 CST 2018
... 老板在找书的过程中我可以干些事情吗....
做爱做的事情找书, 找书, 找书 OK!
书买到了Sun Jan 21 02:16:15 CST 2018主线程开始运行接着我们向ExecutorService提交了一个买书的任务之后我们在干其他的事情。而最后呢Future对象从ExecutorService获取到了执行的结果。我们调用get方法获取到了执行的结果倘若我们没有这个调用那么还是一个并行计算那么老板找书的结果不会立马给我们返回的 转载于:https://www.cnblogs.com/gosaint/p/8320866.html