zoukankan      html  css  js  c++  java
  • JDK并发包

    同步控制:

    重入锁:synchronized的功能扩展
    java.util.concurrent.locks.ReentrantLock

    ReentrantLock的几个重要方法如下:
    lock():获得锁,如果锁已被占用,则等待
    lockInterruptibly():获得锁,但优先响应中断
    tryLock():尝试获得锁,如果成功,返回true,失败返回false。该方法不等待,立即返回
    tryLock(long time, TimeUnit unit):在给定时间内尝试获得锁
    unlock():释放锁

    在重入锁的实现中,主要包含三个要素:
    1.原子状态。原子状态使用CAS操作来存储当前锁的状态,判断锁是否已经被别的线程持有
    2.等待队列。所有没有请求到锁的线程,会进入等待队列进行等待。待有线程释放锁后,系统就能从等待队列中唤醒一个线程,继续工作
    3.阻塞原语park()和unpark(),用来挂起和恢复线程。没有得到锁的线程将会被挂起(有关park()和unpark()方法的介绍,见LockSupport线程阻塞工具类)

    重入锁的搭档:Condition条件
    Condition接口的基本方法如下:
    void await() throws InterruptedException;
    void awaitUninterruptibly();
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    boolean awaitUntil(Date deadline) throws InterruptedException;
    void signal();
    void signalAll();
    上述方法含义如下:
    await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用signal()或signalAll()方法时,线程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待。和Object.wait()方法相似。
    awaitUninterruptibly()方法与await()方法基本相同,但是它不会在等待过程中响应中断。
    singal()方法用户唤醒一个在等待中的线程,singnalAll()方法会唤醒所有等待中的线程。

    信号量(Semaphore):
    信号量是对锁的扩展,为多线程协作提供了更为强大的控制方法。无论是内部锁(synchronized)还是重入锁(ReentrantLock),一次都只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问某一个资源。
    信号量主要提供了以下构造函数:
    public Semaphore(int permits)
    public Semaphore(int permits, boolean fair) // 第二个参数可以指定是否公平
    在构造信号量对象时,必须要指定信号量作为准入数,即同时能申请多少个许可。当每个线程每次只申请一个许可时,就相当于指定了同时有多少个线程可以访问某一个资源。
    信号量的主要方法:
    public void acquire()
    public void acquireUninterruptibly()
    public boolean tryAcquire()
    public boolean tryAcquire(long timeout, TimeUnit unit)
    public void release()

    acquire()方法尝试获得一个准入的许可。若无法获得,则线程会等待,直到有线程释放一个许可或者当前线程被中断。acquireUninterruptibly()方法与acquire()类似,但不响应中断。
    tryAcquire()尝试获得一个许可,成功则返回true,失败则返回false,它不会等待,会立即返回。release()释放一个许可给其它线程。

    示例代码:
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;

    public class SemophoreDemo implements Runnable {

    final Semaphore sema = new Semaphore(5);
    @Override
    public void run() {
        try {
    		sema.acquire();
    		//模拟耗时操作
    		Thread.sleep(2000);
    		System.out.println(Thread.currentThread().getId()+":done!");
    		sema.release();
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    }
    public static void main(String[] args) {
    	ExecutorService exec = Executors.newFixedThreadPool(20);
    	final SemophoreDemo demo = new SemophoreDemo();
    	for(int i=0; i<20; i++){
    		exec.submit(demo);
    	}
    	exec.shutdown();
    }
    

    }

    ReadWriteLock读写锁:
    ReadWriteLock是JDK5中提供的读写分离锁,读写分离可以有效地帮助减少锁竞争,以提升系统新能。如果在系统中,读操作次数远远大于写操作,则读写锁可以很大程度上地提升性能。
    示例代码:

    package com.canww.test1;

    import java.util.Random;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;

    public class ReadWriteLockDemo {

    private static Lock lock = new ReentrantLock();   // 普通重入锁
    private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  // 读写分离锁
    private static Lock readLock = readWriteLock.readLock();   // 读锁
    private static Lock writeLock = readWriteLock.writeLock(); // 写锁
    private int value;
    
    public Object doRead(Lock lock) throws InterruptedException{
    	try{
    		lock.lock();          //模拟读操作
    		Thread.sleep(1000);   //读操作耗时越多,读写锁的优势就越明显
    		return value;
    	}finally{
    		lock.unlock();
    	}
    }
    
    public void doWrite(Lock lock, int index) throws InterruptedException{
    	try{
    		lock.lock();           //模拟写操作
    		Thread.sleep(1000);			
    		value = index;
    	}finally{
    		lock.unlock();
    	}
    }
    
    public static void main(String[] args) {
    	final ReadWriteLockDemo demo = new ReadWriteLockDemo();
    	
    	Runnable read = new Runnable(){
    		public void run() {
    			try {
    				demo.doRead(readLock);  //demo.doRead(lock);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	};
    	
    	Runnable write = new Runnable(){
    		public void run() {
    			try {
    				demo.doWrite(writeLock, new Random().nextInt());  //  demo.doWrite(lock, new Random().nextInt());
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	};
    	
    	for(int i=0; i<18; i++){
    		new Thread(read).start();
    	}
    	
    	for(int i=18; i<20; i++){
    		new Thread(write).start();
    	}
    }
    

    }

  • 相关阅读:
    远程下载文件并设置进度显示
    python调用函数超时设置
    Ubuntu安装PostgreSQL
    sessionStatMap is full
    LdapTemplate忽略ssl证书
    MySQL5.6 Online DDL
    Mysql5.7编译调试(windows环境)
    Disruptor
    mybatis generator自定义文件后缀名
    maven占位符$变量无法替换
  • 原文地址:https://www.cnblogs.com/xbj-2016/p/7764681.html
Copyright © 2011-2022 走看看