Callable,Lock,Condition,ReadWriteLock

简介: Callable,Lock,Condition,ReadWriteLock

Callable接口

Java 5.0在java.util.concurrent提供了一个新的创建执行线程的方式: Callable 接口

Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是Runnable不会返回结果,并且无法抛出经过检查的异常。

Callable需要依赖FutureTask,FutureTask 也可以用作闭锁。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/*
 * 一、创建执行线程的方式三:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
 * 
 * 二、执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。  FutureTask 是  Future 接口的实现类
 */
public class TestCallable {
  public static void main(String[] args) {
    ThreadDemo td = new ThreadDemo();
    //1.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。
    FutureTask<Integer> result = new FutureTask<Integer>(td);
    new Thread(result).start();
    //2.接收线程运算后的结果
    try {
      Integer sum = result.get();  //FutureTask 可用于 闭锁
      System.out.println(sum);
      System.out.println("------------------------------------");
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }
}
class ThreadDemo implements Callable<Integer>{
  @Override
  public Integer call() throws Exception {
    int sum = 0;
    for (int i = 0; i <= 100000; i++) {
      sum += i;
    }
    return sum;
  }
}

Lock同步锁


在Java5.0之前,协调共享对象的访问时可以使用的机制只有synchronized和volatile。


Java 5.0后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。ReentrantLock实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性。但相较于synchronized提供了更高的处理锁的灵活性。


Condition


Condition接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用Object.wait访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock可能与多个Condition对象关联。为了避免兼容性问题,Condition方法的名称与对应的Object版本中的不同。

在Condition对象中,与wait、  notify和notifyAll方法对应的分别是await、  signal和signalAll。

Condition实例实质上被绑定到一一个锁上。要为特定Lock实例获得Condition实例,请使用其newCondition()方法。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
 * 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。
 *  如:ABCABCABC…… 依次递归
 */
public class TestABCAlternate {
  public static void main(String[] args) {
    AlternateDemo ad = new AlternateDemo();
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 1; i <= 20; i++) {
          ad.loopA(i);
        }
      }
    }, "A").start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 1; i <= 20; i++) {
          ad.loopB(i);
        }
      }
    }, "B").start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        for (int i = 1; i <= 20; i++) {
          ad.loopC(i);
          System.out.println("-----------------------------------");
        }
      }
    }, "C").start();
  }
}
class AlternateDemo{
  private int number = 1; //当前正在执行线程的标记
  private Lock lock = new ReentrantLock();
  private Condition condition1 = lock.newCondition();
  private Condition condition2 = lock.newCondition();
  private Condition condition3 = lock.newCondition();
  /**
   * @param totalLoop : 循环第几轮
   */
  public void loopA(int totalLoop){
    lock.lock();
    try {
      //1. 判断
      if(number != 1){
        condition1.await();
      }
      //2. 打印
      for (int i = 1; i <= 1; i++) {
        System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
      }
      //3. 唤醒
      number = 2;
      condition2.signal();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
    try {
    } catch (Exception e) {
      // TODO: handle exception
      e.printStackTrace();
    } 
  }
  public void loopB(int totalLoop){
    lock.lock();
    try {
      //1. 判断
      if(number != 2){
        condition2.await();
      }
      //2. 打印
      for (int i = 1; i <= 1; i++) {
        System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
      }
      //3. 唤醒
      number = 3;
      condition3.signal();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }
  public void loopC(int totalLoop){
    lock.lock();
    try {
      //1. 判断
      if(number != 3){
        condition3.await();
      }
      //2. 打印
      for (int i = 1; i <= 1; i++) {
        System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
      }
      //3. 唤醒
      number = 1;
      condition1.signal();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }
}

     读-写锁ReadWriteLock


     ReadWriteLock维护了一对相关的锁,一一个用于只读操作,另一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。

     ReadWriteLock读取操作通常不会改变共享资源,但执行写入操作时,必须独占方式来获取锁。对于读取操作占多数的数据结构。ReadWriteLock能提供比独占锁更高的并发性。而对于只读的数据结构,其中包含的不变性可以完全不需要考虑加锁操作。

/*
 * 1. ReadWriteLock : 读写锁 一个写线程 100个读线程
 * 
 * 写写/读写 需要“互斥”
 * 读读 不需要互斥
 * 
 */
public class TestReadWriteLock {
  public static void main(String[] args) {
    ReadWriteLockDemo rw = new ReadWriteLockDemo();
    new Thread(new Runnable() {
      @Override
      public void run() {
        rw.set((int)(Math.random() * 101));
      }
    }, "Write:").start();
    for (int i = 0; i < 100; i++) {
      new Thread(new Runnable() {
        @Override
        public void run() {
          rw.get();
        }
      }).start();
    }
  }
}
class ReadWriteLockDemo{
  private int number = 0;
  private ReadWriteLock lock = new ReentrantReadWriteLock();
  //读
  public void get(){
    lock.readLock().lock(); //上锁
    try{
      System.out.println(Thread.currentThread().getName() + " : " + number);
    }finally{
      lock.readLock().unlock(); //释放锁
    }
  }
  //写
  public void set(int number){
    lock.writeLock().lock();
    try{
      System.out.println(Thread.currentThread().getName());
      this.number = number;
    }finally{
      lock.writeLock().unlock();
    }
  }
}
相关文章
|
6月前
|
安全 Java
Synchronized和Lock的区别
Synchronized和Lock的区别
67 0
|
5月前
|
安全 Java
synchronized与Lock
synchronized与Lock
|
6月前
|
存储 安全 算法
掌握Java并发编程:Lock、Condition与并发集合
掌握Java并发编程:Lock、Condition与并发集合
53 0
|
Java
synchronized和lock的区别
synchronized和lock的区别
83 0
|
Java
Lock 和 Synchronized的区别?
本章主要讲解了Lock 和 Synchronized的区别和知识点
52 0
|
Java
synchronized和Lock的区别
synchronized和Lock的区别
71 0
|
安全 Java
一天一个 JUC 工具类 Lock 和 Condition
当谈到Java多线程编程时,我们不可避免地需要处理并发问题。为此Java提供了一个强大的工具包——java.util.concurrent(JUC)
|
安全 Java
浅析wait与synchronized
在Java语言中,Object作为顶级的父类中有一个wait()方法,我们都知道wait()跟notify()作为Java中的线程通信机制,但是你有没有想过:为什么wait方法是在Object中?它为什么不是在Thread中?
141 0
浅析wait与synchronized