java 并发包 编程_java-实战java高并发程序设计-ch3JDK并发包

JDK 并发包

3.1 多线程的同步协助:同步控制

3.1.1 synchronized 扩展功能:重入锁

jdk1.5之前重入锁ReentrantLook性能好于synchronized, 但jdk1.6 开始优化ReentrantLook, 现在二者的性能相差不大。

/**

* @author ChengBing Han

* @date 21:50 2018/6/23

* @description

*/

public class ReentrantLockTest {

static ReentrantLock reentrantLock = new ReentrantLock();

static final Object obj = new Object();

public static void main(String[] args) throws InterruptedException {

final Thread t1 = new Thread(new Runnable() {

public void run() {

System.out.println("T1 lock1");

reentrantLock.lock();

System.out.println("T1 lock2");

reentrantLock.lock();

System.out.println("T1 unlock1");

reentrantLock.unlock();

System.out.println("T1 unlock2");

reentrantLock.unlock();

}

});

final Thread t2 = new Thread(new Runnable() {

public void run() {

synchronized (obj){

System.out.println("t2 lock1");

synchronized (obj){

System.out.println("t2 lock2 ");

}

}

System.out.println("t2 end");

}

});

System.out.println("lock============");

t1.start();

Thread.sleep(1000);

System.out.println("syschronized==================");

t2.start();

}

}

输出:

lock============

T1 lock1

T1 lock2

T1 unlock1

T1 unlock2

syschronized==================

t2 lock1

t2 lock2

t2 end

中断响应

public class Interrupted implements Runnable {

private Integer state = 0;

public Interrupted() {

}

public Interrupted(Integer state) {

this.state = state;

}

static ReentrantLock reentrantLock1 = new ReentrantLock();

static ReentrantLock reentrantLock2 = new ReentrantLock();

public void run() {

try {

if(state == 1) {

reentrantLock1.lockInterruptibly();

System.out.println("state1===lock1");

Thread.sleep(1000);

reentrantLock2.lockInterruptibly();

System.out.println("state1===lock2");

}else if(state == 2){

reentrantLock2.lockInterruptibly();

System.out.println("state2===lock2");

Thread.sleep(1000);

reentrantLock1.lockInterruptibly();

System.out.println("state2===lock1");

}

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

if(reentrantLock1.isHeldByCurrentThread()){

reentrantLock1.unlock();

}

if(reentrantLock2.isHeldByCurrentThread()){

reentrantLock2.unlock();

}

}

}

public static void main(String[] args) throws InterruptedException {

final Interrupted r1 = new Interrupted(1);

final Interrupted r2 = new Interrupted(2);

final Thread t1 = new Thread(r1);

final Thread t2 = new Thread(r2);

t1.start();

Thread.sleep(100);

t2.start();

Thread.sleep(5000);

t2.interrupt();

}

}

输出

state1===lock1

state2===lock2

java.lang.InterruptedException

at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)

at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)

at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)

at com.hcb.thread.c3_1_retrantlookinterrupted.Interrupted.run(Interrupted.java:39)

at java.lang.Thread.run(Thread.java:748)

state1===lock2

锁申请等待限时

一个锁只能锁住某个时间段

public class TimeLock implements Runnable{

static ReentrantLock reentrantLock = new ReentrantLock();

public void run() {

try {

if(reentrantLock.tryLock(3, TimeUnit.SECONDS)){

System.out.println(Thread.currentThread().getName() + " run");

Thread.sleep(6000);

}else {

System.out.println(Thread.currentThread().getName() + "getLock failed");

}

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

//注意finally 这里释放锁的方式

if(reentrantLock.isHeldByCurrentThread()){

reentrantLock.unlock();

}

}

}

public static void main(String[] args) throws InterruptedException {

final TimeLock r1 = new TimeLock();

final Thread thread1 = new Thread(r1);

thread1.setName("t1");

thread1.start();

Thread.sleep(100);

final TimeLock r2 = new TimeLock();

final Thread thread2 = new Thread(r2);

thread2.setName("t2");

thread2.start();

}

}

公平锁

public class FairLock {

//构造函数为true,表示公平

static ReentrantLock reentrantLock = new ReentrantLock(true);

public static class ThreadFair implements Runnable {

public void run() {

while (true) {

try {

reentrantLock.lockInterruptibly();

System.out.println(Thread.currentThread().getName() + " run ");

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

if (reentrantLock.isHeldByCurrentThread()) {

reentrantLock.unlock();

}

}

}

}

}

public static void main(String[] args) {

final ThreadFair threadFair = new ThreadFair();

final Thread fairThread1 = new Thread(threadFair, "fairThread1");

final ThreadFair threadFair2 = new ThreadFair();

final Thread fairThread2 = new Thread(threadFair2, "fairThread2");

fairThread1.start();

fairThread2.start();

}

}

output:

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

fairThread1 run

fairThread2 run

重入锁的condition条件

Condition条件类似与wait,notify方法

备注:Condition的使用注意

1、必须在lock.lock()

和lock.singXX中使用 await/singXX

2、方法名是await 不是wait,wait 是object的方法

b39ba45fb3012503dde953fbdcca74cd.png

public class ConditionLock {

static ReentrantLock reentrantLock = new ReentrantLock();

static Condition condition = reentrantLock.newCondition();

static class ConditionLockThread implements Runnable {

public void run() {

reentrantLock.lock();

try {

System.out.println(Thread.currentThread().getName() + " wait...");

//方法是await不是object的wait

condition.await();

System.out.println(Thread.currentThread().getName() + " end wait...");

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

if(reentrantLock.isHeldByCurrentThread()){

reentrantLock.unlock();

}

}

}

}

public static void main(String[] args) throws InterruptedException {

final ConditionLockThread conditionLockThread1 = new ConditionLockThread();

final Thread thread1 = new Thread(conditionLockThread1, "ConditionLockThread1");

final ConditionLockThread conditionLockThread2 = new ConditionLockThread();

final Thread thread2 = new Thread(conditionLockThread2, "ConditionLockThread2");

thread1.start();

thread2.start();

Thread.sleep(1000);

//必须在 lock.lock/unlock 中间使用

reentrantLock.lock();

condition.signalAll();

reentrantLock.unlock();

}

}

允许多个线程同时访问 信号量Semaphore

可以允许n个线程同时访问,结合公平锁。

7b3ddf3f717597a330feadf6e5f871b4.png

3.1.4 读写锁

ReadWriteLock JDK

/**

* @author ChengBing Han

* @date 14:44 2018/7/7

* @description

*/

public class ReadWriteLockDemo {

public static ReentrantLock lock = new ReentrantLock();

private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();

public static Lock readLock = reentrantReadWriteLock.readLock();

public static Lock writeLock = reentrantReadWriteLock.writeLock();

public static int value;

private static int index = 0;

public static Object handleRead(Lock lock) {

lock.lock();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

System.out.println("read value is " + value);

return value;

}

public static void handleWrite(Lock lock, int newValue) {

lock.lock();

try {

Thread.sleep(1000);

value = newValue;

System.out.println("write value is " + value);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

public static void main(String[] args) {

final long startTime = System.currentTimeMillis();

final Runnable readRunnable = new Runnable() {

public void run() {

handleRead(readLock);

}

};

final Runnable writeRunnable = new Runnable() {

public void run() {

handleWrite(writeLock, ++index);

}

};

for (int i = 0; i < 10; i++) {

final Thread thread = new Thread(readRunnable);

thread.start();

}

for (int i = 0; i < 10; i++) {

final Thread thread = new Thread(writeRunnable);

thread.start();

}

//为什么要在while中输出一些东西呢

//如果还是一个空的While循环,while 会被优化在-Server模式下

while (value != 10){

System.out.print("");

}

final long end = System.currentTimeMillis();

System.out.println("app use :" + (end - startTime)/1000);

}

}

倒计时(线程个数)器: CountDownLatch

可以让n线程都完成任务了,在继续执行某个主线程。例如,火箭发射前有10个检查任务,这时创建10个线程分别处理十个任务,再创建一个发射火箭的线程,每次完成一个检查任务,CountDownLatch 记录一个,这样,可以等10个都完成了,发射火箭的线程再执行。

倒计时器的扩展:循栅栏。

扩展了CountDownLatch,将军让10个士兵为1组, 这样一组的完成类似于CountDownLatch, 如果与多组就用循环栅栏。 可以循环多组。

线程阻塞工具类:LockSupport

提供一些阻塞的功能

3.2 线程复用:线程池

3.2.1什么是线程池

同数据库连接池

3.3.2不要重复造轮子:jdk对线程池的支持

a62ded20a4f84ee178b11c3c27212dab.png

Executors 是什么?

一言蔽之:工厂

Executors的介绍:

/**

* Factory and utility methods for {@link Executor}, {@link

* ExecutorService}, {@link ScheduledExecutorService}, {@link

* ThreadFactory}, and {@link Callable} classes defined in this

* package. This class supports the following kinds of methods:

*

*

*

Methods that create and return an {@link ExecutorService}

* set up with commonly useful configuration settings.

*

Methods that create and return a {@link ScheduledExecutorService}

* set up with commonly useful configuration settings.

*

Methods that create and return a "wrapped" ExecutorService, that

* disables reconfiguration by making implementation-specific methods

* inaccessible.

*

Methods that create and return a {@link ThreadFactory}

* that sets newly created threads to a known state.

*

Methods that create and return a {@link Callable}

* out of other closure-like forms, so they can be used

* in execution methods requiring {@code Callable}.

*

*

* @since 1.5

* @author Doug Lea

*/

1976a9b1badced0327f3580b4152eb36.png

6cb092ebb4cf348a885d617a6a0e62b9.png

线程池说明

41fd7c273acd45214e429cdf8ecda08f.png

固定数量的线程池

弊端:如果线程池中有5个任务,第一个任务

/**

* @author ChengBing Han

* @date 12:19 2018/7/14

* @description

*/

public class FixThreadPoolTest {

public static class MyTask implements Runnable{

public void run() {

final long id = Thread.currentThread().getId();

System.out.println("当前线程的id是: " + id);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public static void main(String[] args) {

final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {

newFixedThreadPool.submit(new MyTask());

}

}

}

通过输出可以看到,10个任务,用池子中的了5个线程

**output:**

当前线程的id是: 13

当前线程的id是: 15

当前线程的id是: 16

当前线程的id是: 13

当前线程的id是: 14

当前线程的id是: 17

当前线程的id是: 15

当前线程的id是: 16

当前线程的id是: 13

当前线程的id是: 14

异常处理

/**

* @author ChengBing Han

* @date 12:19 2018/7/14

* @description

*/

public class FixThreadPoolTest {

static boolean flag = true;

public static class MyTask implements Runnable{

public void run() {

if(flag){

flag=false;

System.out.println("出现异常");

System.out.println(1/0);

System.out.println("异常结束");

}

final long id = Thread.currentThread().getId();

System.out.println("当前线程的id是: " + id);

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public static void main(String[] args) {

final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {

newFixedThreadPool.submit(new MyTask());

}

newFixedThreadPool.shutdown();

}

}

output:

出现异常

当前线程的id是: 11

当前线程的id是: 14

当前线程的id是: 15

当前线程的id是: 13

当前线程的id是: 12

当前线程的id是: 14

当前线程的id是: 15

当前线程的id是: 11

当前线程的id是: 13

**结论:根据上述输出,可以发现,线程次中有10次调用,某次发生异常,不会影响其它的9次**

定时线程:

/**

* @author ChengBing Han

* @date 12:24 2018/7/14

* @description

*/

public class SheduleThreadPoolTest {

public static class MyTask implements Runnable{

public void run() {

System.out.println("Thread is run which id is : " + Thread.currentThread().getId());

}

}

public static void main(String[] args) {

final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

scheduledExecutorService.scheduleAtFixedRate(new MyTask(),10,1,TimeUnit.SECONDS);

}

}

*注意定时的这个线程池和上述的newFixedThreadPool不同,一旦某个任务出现调度异常,那么后面的任务都不会再执行。==》做好异常处理工作。

*定时任务的两个方法不同之处在于

scheduleAtFixedRate: 每隔2秒调度一个任务,但是一个任务的时间是8秒(大于2秒)那么实际是8秒调度一个任务。

scheduleWithFixedDelay: 隔2秒调度一个任务,但是一个任务的时间是8秒(大于2秒)那么实际是8+2秒调度一个任务。

3.2.3 线程池的内部实现:

该部分待看书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值