0%

线程协作

文章字数:431,阅读全文大约需要1分钟

一、等待和通知(Object方法)

1.1等待和通知

  • wait()等待方
  1. 获取对象的锁
  2. 循环里判断条件是否满足,不满足调用wait()方法
  3. 满足执行业务
  • notify/notifyAll通知方
  1. 获取对象锁
  2. 改变对象条件
  3. 通知所有等待对象的线程
  • wait()用于休眠当前线程,需要调用同对象的notify()或者notifyAll()方法唤醒。
  • wait()notify()notifyAll()需要先获取到线程的锁,即synchronized包裹。
  • notify()唤醒一个线程,notifyAll()唤醒所有。建议都使用nofityAll()方法,内部用while()循环判断是否满足条件,不满足继续wait()。否则会出现信号丢失情况。

1.2利用等待通知实现超时连接池

  • 连接池
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    // 保存链接的地方
    private static LinkdList<Connection> pool = new LinkedList<>();

    // 构造方法里初始化若干数量的数据库链接
    public DBPool(int initalSize) {
    if(initalSize > 0) {
    for(int i = 0; i < initalSize; i++) {
    pool.addLast(SqlConnectServer.fetchConnection());
    }
    }
    }

    // 获取线程,设置超时时间为mills,超时返回null。
    public Connection fetchConn(long mills) {
    synchronized(pool) {
    // 不超时,等到有为止
    if (mills < 0) {
    while(pool.isEmpty()) {
    pool.wait();
    }
    return pool.removeFirst();
    } else{
    // 什么时候超时
    long overtime = System.currentTimeMillis() + mills;
    // 剩余时间
    long remain = mills;
    // 池为空且还有等待时间
    while(pool.isEmpty() && remain > 0) {
    pool.wait(remain);
    remain = overtime - System.currentTimeMillis();
    }
    Connection result = null;
    if(!pool.isEmpty()) {
    result = pool.removeFirst();
    }
    return result;
    }
    }
    }

    public void releseConn(Connection conn) {
    if(conn != null) {
    synchronized(pool) {
    pool.addLast(conn);
    pool.notifyAll();
    }
    }
    }

二、join方法(Thread的)

功能

  1. 线程A执行了线程B的join()方法,则线程A必须等线程B执行之后才能继续自己的工作。

三、yield()、sleep()、wait()、notify()等对锁的影响

  1. yield()交出执行权,不释放持有的锁
  2. sleep()休眠,不释放持有的锁
  3. wait()方法执行前必须要持有锁,调用了wait()方法之后,自动释放锁。被唤醒时自动持有锁
  4. notify()方法执行前必须要持有锁,调用时本身不会释放锁。所以一般在synchroized代码块最后。