ReentrantLock
public class JdkLockTest implements Runnable{
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private static int i = 0;
public static void main(String[] args) {
JdkLockTest jdkLockTest = new JdkLockTest();
Thread t1 = new Thread(jdkLockTest);
Thread t2 = new Thread(jdkLockTest);
Thread t3 = new Thread(jdkLockTest);
t1.start();
t2.start();
t3.start();
}
@Override
public void run(){
lock .lock();
try {
System.out.println("开始等待2s");
condition.await(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadName=" + Thread.currentThread().getName());
for(int j=0; j<1000000; j++){
i++;
}
System.out.println("i = " + i);
lock.unlock();
}
}
ReentrantLock其他方法
- getHoldCount() 查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次数
- getQueueLength()返回正等待获取此锁的线程估计数,比如启动10个线程,1个线程获得锁,此时返回的是9
- getWaitQueueLength(Condition condition)返回等待与此锁相关的给定条件的线程估计数。比如10个线程,用同一个condition对象,并且此时这10个线程都执行了condition对象的await方法,那么此时执行此方法返回10
- hasWaiters(Condition condition)查询是否有线程等待与此锁有关的给定条件(condition),对于指定contidion对象,有多少线程执行了condition.await方法
- hasQueuedThread(Thread thread)查询给定线程是否等待获取此锁
- hasQueuedThreads()是否有线程等待此锁
- isFair()该锁是否公平锁
- isHeldByCurrentThread() 当前线程是否保持锁锁定,线程的执行lock方法的前后分别是false和true
- isLock()此锁是否有任意线程占用
- lockInterruptibly()如果当前线程未被中断,获取锁
- tryLock()尝试获得锁,仅在调用时锁未被线程占用,获得锁
- tryLock(long timeout TimeUnit unit)如果锁在给定等待时间内没有被另一个线程保持,则获取该锁
Semaphore
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i=0; i<10; i++){
executorService.execute(new Test(semaphore));
}
executorService.shutdown();
}
}
class Test implements Runnable{
private Semaphore semaphore;
private int i=0;
public Test(){}
public Test(Semaphore semaphore){
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
for(int j=0; j<1000000; j++){
i++;
}
System.out.println("i = " + i);
System.out.println("当前线程=====》"+ Thread.currentThread().getName());
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
其他方法,(摘自网络)
Semaphore的方法如下:
——Semaphore(permits) 初始化许可证数量的构造函数
——Semaphore(permits,fair) 初始化许可证数量和是否公平模式的构造函数
——isFair() 是否公平模式FIFO
——availablePermits() 获取当前可用的许可证数量
——acquire()
当前线程尝试去阻塞的获取1个许可证。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了1个可用的许可证,则会停止等待,继续执行。
当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
——acquire(permits)
当前线程尝试去阻塞的获取permits个许可证。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了n个可用的许可证,则会停止等待,继续执行。
当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
——acquierUninterruptibly()
当前线程尝试去阻塞的获取1个许可证(不可中断的)。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了1个可用的许可证,则会停止等待,继续执行。
——acquireUninterruptibly(permits)
当前线程尝试去阻塞的获取permits个许可证。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了n个可用的许可证,则会停止等待,继续执行。
——tryAcquire()
当前线程尝试去获取1个许可证。
此过程是非阻塞的,它只是在方法调用时进行一次尝试。
如果当前线程获取了1个可用的许可证,则会停止等待,继续执行,并返回true。
如果当前线程没有获得这个许可证,也会停止等待,继续执行,并返回false。
——tryAcquire(permits)
当前线程尝试去获取permits个许可证。
此过程是非阻塞的,它只是在方法调用时进行一次尝试。
如果当前线程获取了permits个可用的许可证,则会停止等待,继续执行,并返回true。
如果当前线程没有获得permits个许可证,也会停止等待,继续执行,并返回false。
——tryAcquire(timeout,TimeUnit)
当前线程在限定时间内,阻塞的尝试去获取1个许可证。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了可用的许可证,则会停止等待,继续执行,并返回true。
当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
——tryAcquire(permits,timeout,TimeUnit)
当前线程在限定时间内,阻塞的尝试去获取permits个许可证。
此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:
当前线程获取了可用的permits个许可证,则会停止等待,继续执行,并返回true。
当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
——release() 当前线程释放1个可用的许可证。
——release(permits) 当前线程释放permits个可用的许可证。
——drainPermits() 当前线程获得剩余的所有可用许可证。
——hasQueuedThreads() 判断当前Semaphore对象上是否存在正在等待许可证的线程。
——getQueueLength() 获取当前Semaphore对象上是正在等待许可证的线程数量。
ReadWriteLock 当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。
public class ReadWriteLockTest { public static void main(String[] args) { TestReadWrite testReadWrite = new TestReadWrite(); for(int i=0; i<10; i++){ new Thread(testReadWrite::read).start(); } for(int j=0; j<10; j++) { new Thread(() -> testReadWrite.write("你好")).start(); } } } class TestReadWrite{ private String data; private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void read(){ readWriteLock.readLock().lock();//线程只能读,不能写 System.out.println(Thread.currentThread().getName() + "读取数据========"); try { Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "读取完数据 :" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } } public void write(String data){ readWriteLock.writeLock().lock();//不允许其他线程读写操作 System.out.println(Thread.currentThread().getName() + "写数据========"); try { Thread.sleep((long) (Math.random() * 1000)); this.data = data; System.out.println(Thread.currentThread().getName() + "写数据完成 ==" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); } } }
CountDownLacth
某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为n new CountDownLatch(n)
,每当一个任务线程执行完毕,就将计数器减1 countdownlatch.countDown()
,当计数器的值变为0时,在CountDownLatch上 await()
的线程就会被唤醒。
public class CountDownLacthTest { public static void main(String[] args) { final CountDownLatch countDown = new CountDownLatch(2); Thread t1 = new Thread(() -> { System.out.println("线程t1开始执行-------------"); try { System.out.println("线程t1等待其他线程-------------"); countDown.await(); System.out.println("线程t1继续执行-------------"); } catch (InterruptedException e) { e.printStackTrace(); } },"t1"); Thread t2 = new Thread(() -> { try { System.out.println("线程t2开始执行-------------"); Thread.sleep((long) (Math.random()*1000)); System.out.println("线程t2执行完毕-------------"); countDown.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } },"t2"); Thread t3 = new Thread(() -> { try { System.out.println("线程t3开始执行-------------"); Thread.sleep((long) (Math.random()*1000)); System.out.println("线程t3执行完毕-------------"); countDown.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } },"t3"); t1.start(); t2.start(); t3.start(); } }
CyclicBarrier 注意:当线程数和parties不一致的时候有可能发生阻塞问题!最后剩下的线程数不足parties,无法继续执行下去
public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3);//当有3个线程到达时,共同执行 //final CyclicBarrier cb = new CyclicBarrier(3, () -> System.out.println("********我最先执行***********")); for (int i = 0; i < 3; i++) { Runnable runnable = () -> { try { Thread.sleep((long) (Math.random() * 1000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); cb.await();//到此如果没有达到公共屏障点,则该线程处于等待状态,如果达到公共屏障点则所有处于等待的线程都继续往下运行 Thread.sleep((long) (Math.random() * 1000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); cb.await(); Thread.sleep((long) (Math.random() * 1000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); cb.await(); } catch (Exception e) { e.printStackTrace(); } }; service.execute(runnable); } service.shutdown(); } }