java面试笔试题:同步和异步有何异同

简介: 如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取.
如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取.

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率.


 

    Java同步:

    基本概念:

    每个Object都会有1个锁.

    同步就是串行使用一些资源.

    (说明:以下有些例子为了突出重点,省略了不必要的代码.非凡是省掉了一些成员变量,就是需要同步的对象.)

    1. 多线程中对共享、可变的数据进行同步.

    对于函数中的局部变量没必要进行同步.

    对于不可变数据,也没必要进行同步.

    多线程中访问共享可变数据才有必要.

    2. 单个线程中可以使用synchronized,而且可以嵌套,但无意义.

    class Test {

    public static void main(String[] args) {

    Test t = new Test();

    synchronized(t) {

    synchronized(t) {

    System.out.println("ok!");

    }

    }

    }

    }

    3. 对象实例的锁

    class Test{

    public synchronized void f1(){

    //do something here

    }

    public void f2(){

    synchronized(this){

    //do something here

    }

    }

    }

    上面的f1()和f2()效果一致, synchronized取得的锁都是Test某个实列(this)的锁.

    比如: Test t = new Test();

    线程A调用t.f2()时, 线程B无法进入t.f1(),直到t.f2()结束.

    作用: 多线程中访问Test的同一个实例的同步方法时会进行同步.

    4. class的锁

    class Test{

    final static Object o= new Object();

    public static synchronized void f1(){

    //do something here

    }

    public static void f2(){

    synchronized(Test.class){

    //do something here

    }

    }

    public static void f3(){

    try {

    synchronized (Class.forName("Test")) {

    //do something here

    }

    }

    catch (ClassNotFoundException ex) {

    }

    }

    public static void g(){

    synchronized(o){

    //do something here

    }

    }

    }

    上面f1(),f2(),f3(),g()效果一致

    f1(),f2(),f3()中synchronized取得的锁都是Test.class的锁.

    g()是自己产生一个对象o,利用o的锁做同步

    作用: 多线程中访问此类或此类任一个实例的同步方法时都会同步. singleton模式lazily initializing属于此类.

    5. static method

    class Test{

    private static int v = 0;

    public static void f1(){

    //do something, 但函数中没用用到v

    }

    public synchronized static void f2(){

    //do something, 函数中对v进行了读/写.

    }

    }

    多线程中使用Test的某个实列时,

    (1) f1()是线程安全的,不需要同步

    (2) f2()这个静态方法中使用了函数外静态变量,所以需要同步.

     Java异步:

    一.    它要能适应不同类型的请求:

    本节用 makeString来说明要求有返回值的请求.用displayString来说明不需要返回值的请求.

    二.    要能同时并发处理多个请求,并能按一定机制调度:

    本节将用一个队列来存放请求,所以只能按FIFO机制调度,你可以改用LinkedList,就可以简单实现一个优先级(优先级高的addFirst,低的addLast).

    三.    有能力将调用的边界从线程扩展到机器间(RMI)

    四.    分离过度耦合,如分离调用句柄(取货凭证)和真实数据的实现.分离调用和执行的过程,可以尽快地将调返回.

    现在看具体的实现:

    public interface Axman {

    Result resultTest(int count,char c);

    void noResultTest(String str);

    }

    这个接口有两个方法要实现,就是有返回值的调用resultTest和不需要返回值的调用

    noResultTest, 我们把这个接口用一个代理类来实现,目的是将方法调用转化为对象,这样就可以将多个请求(多个方法调)放到一个容器中缓存起来,然后统一处理,因为 Java不支持方法指针,所以把方法调用转换为对象,然后在这个对象上统一执行它们的方法,不仅可以做到异步处理,而且可以将代表方法调用的请求对象序列化后通过网络传递到另一个机器上执行(RMI).这也是Java回调机制最有力的实现.

    一个简单的例子.

    如果 1: 做A

    如果 2: 做B

    如果 3: 做C

    如果有1000个情况,你不至于用1000个case吧?以后再增加呢?

    所以如果C/C++程序员,会这样实现: (c和c++定义结构不同)

    type define struct MyStruct{

    int mark;

    (*fn) ();

    } MyList;

    然后你可以声明这个结构数据:

    {1,A,

    2,B

    3,C

    }

    做一个循环:

    for(i=0;i<length;i++) {

    if(数据组[i].mark == 传入的值) (数据组[i].*fn)();

    }

    简单说c/c++中将要被调用的涵数可以被保存起来,然后去访问,调用,而Java中,我们无法将一个方法保存,除了直接调用,所以将要调用的方法用子类来实现,然后把这些子类实例保存起来,然后在这些子类的实现上调用方法:

    interface My{

    void test();

    }


登录 后,您就出现在这里。     linghu_java
目录
相关文章
|
2天前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
19天前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
6天前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
11天前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
29 5
|
10天前
|
存储 Java
[Java]面试官:你对异常处理了解多少,例如,finally中可以有return吗?
本文介绍了Java中`try...catch...finally`语句的使用细节及返回值问题,并探讨了JDK1.7引入的`try...with...resources`新特性,强调了异常处理机制及资源自动关闭的优势。
14 1
|
11天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
22 1
|
19天前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
22 3
|
23天前
|
Java
Java面试题之cpu占用率100%,进行定位和解决
这篇文章介绍了如何定位和解决Java服务中CPU占用率过高的问题,包括使用top命令找到高CPU占用的进程和线程,以及使用jstack工具获取堆栈信息来确定问题代码位置的步骤。
60 0
Java面试题之cpu占用率100%,进行定位和解决
|
9天前
|
算法 Java
JAVA 二叉树面试题
JAVA 二叉树面试题
11 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。