java线程并发库_JDK的多线程与并发库

1.创建多线程

public classMultiThread {public static voidmain(String[] args) {//通过继承Thread类

Thread thread = newThread(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

System.out.println("2:" + this.getName());

}

}

};

thread.start();//通过实现Runnable接口

Thread thread2 = new Thread(newRunnable(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

}

}

});

thread2.start();//如果既继承runnable接口又实现了Thread类, 会执行哪个?

newThread(newRunnable(){public voidrun() {while(true){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

}

}

}

){public voidrun() {while(true){try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

}

}

}.start();

}

}

2.定时器Timer

定时任务就是靠多线程实现的

public classTimerTest {private static int count = 0;public static voidmain(String[] args) {class MyTimerTask extendsTimerTask{

@Overridepublic voidrun() {

count= (count+1)%2;

System.out.println("bombing!");new Timer().schedule(new MyTimerTask(),2000+2000*count);

}

}new Timer().schedule(new MyTimerTask(), 2000);while(true){

System.out.println(newDate().getSeconds());try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

3.互斥 synchronized

保证线程安全(数据完整性)

public classMultiThreadMutex {public static voidmain(String[] args) {newMultiThreadMutex().init();

}private voidinit(){final Outputer outputer = newOutputer();new Thread(newRunnable(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(10);

}catch(InterruptedException e) {

e.printStackTrace();

}

outputer.output("javaIsAPurelyObjectOrientedProgrammingLanguage");

}

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(10);

}catch(InterruptedException e) {

e.printStackTrace();

}

outputer.output3("c++IsAMulti-paradigmSystems-levelProgrammingLanguage");

}

}

}).start();

}static classOutputer{public voidoutput(String name){int len =name.length();synchronized (Outputer.class)

{for(int i=0;i

System.out.print(name.charAt(i));

}

System.out.println();

}

}public synchronized voidoutput2(String name){int len =name.length();for(int i=0;i

System.out.print(name.charAt(i));

}

System.out.println();

}public static synchronized voidoutput3(String name){int len =name.length();for(int i=0;i

System.out.print(name.charAt(i));

}

System.out.println();

}

}

}

4.同步 wait/notify

保证线程间执行次序

//1. wait notify成对出现, 并且处于互斥锁的范围内//2. 要用while(condition)围住mutex.wait(), 因为存在虚假唤醒

public classMultiThreadSynchronization {public static voidmain(String[] args) {final Business business = newBusiness();newThread(newRunnable() {

@Overridepublic voidrun() {for(int i=1;i<=50;i++){

business.sub(i);

}

}

}

).start();for(int i=1;i<=50;i++){

business.main(i);

}

}

}classBusiness {private boolean bShouldSub = true;public synchronized void sub(inti) {while (!bShouldSub) {try{this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}for (int j = 1; j <= 10; j++) {

System.out.println("sub thread sequence of " + j + ",loop of " +i);

}

bShouldSub= false;this.notify();

}public synchronized void main(inti) {while(bShouldSub) {try{this.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}for (int j = 1; j <= 100; j++) {

System.out.println("main thread sequence of " + j + ",loop of " +i);

}

bShouldSub= true;this.notify();

}

}

5.线程间传递参数

共享变量

/多个线程共享变量//以类中变量为中介; 以传入的共同参数为中介; 匿名内部类以主线程main中变量为中介;

public classMultiThreadShareData {public static voidmain(String[] args) {//传入共享参数 每个线程执行相同的代码

ShareData1 data1 = newShareData1();newThread(data1).start();newThread(data1).start();//传入共享参数

ShareData2 data2 = newShareData2();new Thread(newMyRunnable1(data2)).start();new Thread(newMyRunnable2(data2)).start();//匿名内部类实现变量的写法更简洁, 不需要传参

final ShareData2 data3 = newShareData2();new Thread(newRunnable(){

@Overridepublic voidrun() {

data3.decrement();

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun() {

data3.increment();

}

}).start();

}

}//方式1. 如果每个线程执行相同的代码 -> 多个Thread共享同一个runnable中的对象 少有可能

class ShareData1 implementsRunnable {private int count = 100;

@Overridepublic voidrun() {while (true) {synchronized(this) {

count--;

}

}

}

}//方式2.

classShareData2 {private int j = 0;public synchronized voidincrement() {

j++;

}public synchronized voiddecrement() {

j--;

}

}class MyRunnable1 implementsRunnable {privateShareData2 data1;publicMyRunnable1(ShareData2 data1) {this.data1 =data1;

}public voidrun() {

data1.decrement();

}

}class MyRunnable2 implementsRunnable {privateShareData2 data1;publicMyRunnable2(ShareData2 data1) {this.data1 =data1;

}public voidrun() {

data1.increment();

}

}

管道

public classMultiThreadPipe {public static voidmain(String[] args) {

PipedOutputStream pos= newPipedOutputStream();

PipedInputStream pis= newPipedInputStream();try{

pos.connect(pis);

}catch(IOException e) {

e.printStackTrace();

}newConsumer(pis).start();newProducer(pos).start();

}

}class Producer extendsThread {privatePipedOutputStream pos;publicProducer(PipedOutputStream pos) {this.pos =pos;

}public voidrun() {int i = 8;try{try{

Thread.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();

}

pos.write(i);

}catch(IOException e) {

e.printStackTrace();

}

}

}class Consumer extendsThread {privatePipedInputStream pis;publicConsumer(PipedInputStream pis) {this.pis =pis;

}public voidrun() {try{

System.out.println(pis.read());

}catch(IOException e) {

e.printStackTrace();

}

}

}

6.ThreadLocal

该变量形式上共享, 但却是by线程独立

public classThreadLocalExample {private static ThreadLocal x = new ThreadLocal();public static voidmain(String[] args) {for (int i = 0; i < 2; i++) {new Thread(newRunnable() {

@Overridepublic voidrun() {int data = newRandom().nextInt();

System.out.println(Thread.currentThread().getName()+ " has put data :" +data);

x.set(data);

Person.getInstance().setName("name" +data);

Person.getInstance().setAge(data);newA().print();newB().print();

}

}).start();

}

}static classA{public voidprint(){int data =x.get();

System.out.println("A from " +Thread.currentThread().getName()+ " get data :" +data);

Person myData=Person.getInstance();

System.out.println("A from " +Thread.currentThread().getName()+ " getMyData: " + myData.getName() + "," +myData.getAge());

}

}static classB{public voidprint(){int data =x.get();

System.out.println("B from " +Thread.currentThread().getName()+ " get data :" +data);

Person myData=Person.getInstance();

System.out.println("B from " +Thread.currentThread().getName()+ " getMyData: " + myData.getName() + "," +myData.getAge());

}

}

}//javaBean的by线程的单例

classPerson {private static ThreadLocal personThreadLocal = new ThreadLocal();privatePerson(){}public static /*无需synchronized*/Person getInstance(){

Person instance=personThreadLocal.get();if(instance == null){

instance= newPerson();

personThreadLocal.set(instance);

}returninstance;

}privateString name;private intage;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}

}

ThreadLocal实现原理

public classThreadLocalSimulation {private static Map threadData = new HashMap(); //核心

public static voidmain(String[] args) {for (int i = 0; i < 2; i++) {new Thread(newRunnable() {

@Overridepublic voidrun() {int data = newRandom().nextInt();

System.out.println(Thread.currentThread().getName()+ " has put data :" +data);

threadData.put(Thread.currentThread(), data);newA().get();newB().get();

}

}).start();

}

}static classA{public voidget(){int data =threadData.get(Thread.currentThread());

System.out.println("A from " +Thread.currentThread().getName()+ " get data :" +data);

}

}static classB{public voidget(){int data =threadData.get(Thread.currentThread());

System.out.println("B from " +Thread.currentThread().getName()+ " get data :" +data);

}

}

}

7. 线程池

池化技术都是防止频繁开关来提高系统性能, 代价是必须损耗一定空间来保存池

//池化技术之线程池

public classThreadPoolTest {public static voidmain(String[] args) {

ExecutorService threadPool= Executors.newFixedThreadPool(3); //限制线程数量//ExecutorService threadPool = Executors.newCachedThreadPool();//动态控制线程数量//ExecutorService threadPool = Executors.newSingleThreadExecutor();//跟一个线程类似, 但可以保证线程挂了有新线程接替

for(int i=1; i<=10; i++){final int task =i;

threadPool.execute(newRunnable(){

@Overridepublic voidrun() {for(int j = 1; j <= 10; j++){try{

Thread.sleep(20);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+ " task:" + task + " loop:" +j);

}

}

});

}

System.out.println("all of 10 tasks have committed!");

threadPool.shutdown();//如果是shutdownNow方法会停止正在执行的任务//带定时器的线程池 schedule方法:xx时间以后执行; scheduleAtFiexedRate方法:xx时间后每隔yy时间执行

Executors.newScheduledThreadPool(3).scheduleAtFixedRate(newRunnable() {

@Overridepublic voidrun() {

System.out.println("bombing!");

}

},6, 2, TimeUnit.SECONDS);

}

}

8. Callable接口与Future

能实现返回线程执行结果 的效果

//返回结果的任务

public classCallableAndFuture {public static voidmain(String[] args) {//其一

ExecutorService threadPool =Executors.newSingleThreadExecutor();

Future future = threadPool.submit( //submit Callable而非execute Runnable

new Callable() {public String call() throwsException {//模拟handling

Thread.sleep(2000);return "hello";

};

});

System.out.println("等待结果");try{

System.out.println("拿到结果:" + future.get()); //阻塞等待结果,还有个get方法的重载版本,带超时参数, 超时抛异常. future/get的特点在于, 我们可以把任务合理分解, 在需要任务结果时调用get

} catch(InterruptedException e) {

e.printStackTrace();

}catch(Exception e) {

e.printStackTrace();

}

threadPool.shutdown();//不用该函数主线程是不会退出的//其二//ExecutorCompletionService包装线程池, take方法返回最先完成的Future任务

ExecutorService threadPool2 = Executors.newFixedThreadPool(10);

CompletionService completionService = new ExecutorCompletionService(threadPool2);for (int i = 1; i <= 10; i++) {final int seq =i;

completionService.submit(new Callable() {

@Overridepublic Integer call() throwsException {//模拟handling

Thread.sleep(new Random().nextInt(5000));returnseq;

}

});

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

System.out.println(completionService.take().get());

}catch(InterruptedException e) {

e.printStackTrace();

}catch(ExecutionException e) {

e.printStackTrace();

}

}

threadPool2.shutdown();

}

}

9.Lock

ReentrantLock是具有synchronized功能的类

ReentrantReadWriteLock 粒度更细, 读与读不互斥, 写与写互斥,  读与写互斥

//使用Lock改写synchronized例子

public classLockTest {public static voidmain(String[] args) {newLockTest().init();

}private voidinit(){final Outputer outputer = newOutputer();new Thread(newRunnable(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(100);

}catch(InterruptedException e) {

e.printStackTrace();

}

outputer.output("javaIsAPurelyObjectOrientedProgrammingLanguage");

}

}

}).start();new Thread(newRunnable(){

@Overridepublic voidrun() {while(true){try{

Thread.sleep(100);

}catch(InterruptedException e) {

e.printStackTrace();

}

outputer.output("c++IsAMulti-paradigmSystems-levelProgrammingLanguage");

}

}

}).start();

}static classOutputer {

Lock lock= newReentrantLock();public voidoutput(String name) {int len =name.length();

lock.lock();try{for (int i = 0; i < len; i++) {

System.out.print(name.charAt(i));

}

System.out.println();

}finally{

lock.unlock();

}

}

}

}

使用读写锁模拟缓存

//模拟缓存//加锁解锁要一致: 解没加过的锁会抛出异常; 加锁不解会造成死锁

public classCacheSimulation {public static voidmain(String[] args) {for (int i = 0; i < 10; ++i) {new Thread(newRunnable() {

@Overridepublic voidrun() {

String i= (String) getData("key");//out.println()参数为常量无并发问题; 为表达式时存在并发问题

System.out.println(i);

}

}).start();

}

}private static Map cache = new HashMap(); //保存缓存

private static ReadWriteLock rwl = newReentrantReadWriteLock();public staticObject getData(String key) {

rwl.readLock().lock();

Object value=cache.get(key);if (value == null) {

rwl.readLock().unlock();

rwl.writeLock().lock();if (cache.get(key) == null) { //防止几个线程都阻塞在writeLock.lock()

value = "abcde"; //模拟获取数据

System.out.println("get");

cache.put(key, value);

}

rwl.writeLock().unlock();

}returnvalue;

}

}

10.Condition

Condition具有wait/notify功能的类, 同样要配合Lock使用. 但与synchronized的waitnotify不同, 这里同一个Lock下可以创建多个Condition对象, 来实现粒度更细的控制

一个condition

//使用Condition改写线程同步示例, Condition由Lock.newCondition()而来//Condition.await/signal 对应 Mutex.wait/notify

public classConditionTest {public static voidmain(String[] args) {final Business business = newBusiness();new Thread(newRunnable() {

@Overridepublic voidrun() {for (int i = 1; i <= 50; i++) {

business.sub(i);

}

}

}).start();for (int i = 1; i <= 30; i++) {

business.main(i);

}

}static classBusiness {

Lock lock= newReentrantLock();

Condition condition=lock.newCondition();private boolean bShouldSub = true;public void sub(inti) {

lock.lock();try{while (!bShouldSub) {try{

condition.await();

}catch(Exception e) {

e.printStackTrace();

}

}for (int j = 1; j <= 10; j++) {

System.out.println("sub thread sequence of " + j + ",loop of " +i);

}

bShouldSub= false;

condition.signal();

}finally{

lock.unlock();

}

}public void main(inti) {

lock.lock();try{while(bShouldSub) {try{

condition.await();

}catch(Exception e) {

e.printStackTrace();

}

}for (int j = 1; j <= 20; j++) {

System.out.println("main thread sequence of " + j + ",loop of " +i);

}

bShouldSub= true;

condition.signal();

}finally{

lock.unlock();

}

}

}

}

两个condition,  下面模拟了数组阻塞队列

//有界缓冲区/数组阻塞队列 的模拟

classArrayBlockingQueueSimulation {final Lock lock = newReentrantLock();final Condition notFull =lock.newCondition();final Condition notEmpty =lock.newCondition();final Object[] items = new Object[100]; //长度

int putptr, takeptr, count; //初始为0

public void put(Object x) throwsInterruptedException {

lock.lock();try{while (count ==items.length) {

notFull.await();

}

items[putptr]=x;if (++putptr ==items.length) {

putptr= 0;

}++count;

notEmpty.signal();

}finally{

lock.unlock();

}

}public Object take() throwsInterruptedException {

lock.lock();try{while (count == 0) {

notEmpty.await();

}

Object x=items[takeptr];if (++takeptr ==items.length) {

takeptr= 0;

}--count;

notFull.signal();returnx;

}finally{

lock.unlock();

}

}

}

三个condition,  如下实现了三个线程轮流执行

public classThreeThreadsSynchronization {public static voidmain(String[] args) {final Business business = newBusiness();new Thread(newRunnable() {

@Overridepublic voidrun() {for (int i = 1; i <= 50; i++) {

business.sub2(i);

}

}

}).start();new Thread(newRunnable() {

@Overridepublic voidrun() {for (int i = 1; i <= 50; i++) {

business.sub3(i);

}

}

}).start();for (int i = 1; i <= 50; i++) {

business.main(i);

}

}static classBusiness {

Lock lock= newReentrantLock();

Condition condition1=lock.newCondition();

Condition condition2=lock.newCondition();

Condition condition3=lock.newCondition();private int shouldSub = 1;public void sub2(inti) {

lock.lock();try{while (shouldSub != 2) {try{

condition2.await();

}catch(Exception e) {

e.printStackTrace();

}

}for (int j = 1; j <= 20; j++) {

System.out.println("sub2 thread sequence of " + j + ",loop of " +i);

}

shouldSub= 3;

condition3.signal();

}finally{

lock.unlock();

}

}public void sub3(inti) {

lock.lock();try{while (shouldSub != 3) {try{

condition3.await();

}catch(Exception e) {

e.printStackTrace();

}

}for (int j = 1; j <= 10; j++) {

System.out.println("sub3 thread sequence of " + j + ",loop of " +i);

}

shouldSub= 1;

condition1.signal();

}finally{

lock.unlock();

}

}public void main(inti) {

lock.lock();try{while (shouldSub != 1) {try{

condition1.await();

}catch(Exception e) {

e.printStackTrace();

}

}for (int j = 1; j <= 30; j++) {

System.out.println("main thread sequence of " + j + ",loop of " +i);

}

shouldSub= 2;

condition2.signal();

}finally{

lock.unlock();

}

}

}

}

11. Semaphore

Semaphore信号量, 互斥锁保证多个线程同时访问同一个资源时的线程安全性, 信号量让线程动态匹配现有资源数, 来保证同时访问多个资源时的线程安全性, 并发更高.

Lock是哪个线程拿哪个线程负责释放; 信号量可以是一个线程获取, 另一个线程释放, 这个特性能用于死锁恢复.

public classSemaphoreTest {public static voidmain(String[] args) {

ExecutorService service=Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(3);for (int i = 0; i < 10; i++) {

Runnable runnable= newRunnable() {public voidrun() {try{

semaphore.acquire();//线程进入时获取信号量

} catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("线程" + Thread.currentThread().getName() + "进入,当前已有" + (3 - semaphore.availablePermits()) + "个并发");try{

Thread.sleep((long) (Math.random() * 1000));

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("线程" + Thread.currentThread().getName() + "即将离开");

semaphore.release();//线程结束时释放信号量//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元

System.out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3 - semaphore.availablePermits()) + "个并发");

}

};

service.execute(runnable);

}

service.shutdown();

}

}

12. CyclicBarrier

多个线程阶段点同步

public classCyclicBarrierTest {public static voidmain(String[] args) {

ExecutorService service=Executors.newCachedThreadPool();final CyclicBarrier cb = new CyclicBarrier(3);for (int i = 0; i < 3; i++) {

Runnable runnable= newRunnable() {public voidrun() {try{//模拟handling

Thread.sleep((long) (Math.random() * 1000));

System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有"

+ (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走" : "正在等候"));

cb.await();//第一个同步点

Thread.sleep((long) (Math.random() * 1000));

System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有"

+ (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走" : "正在等候"));

cb.await();//第二个同步点

Thread.sleep((long) (Math.random() * 1000));

System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有"

+ (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走" : "正在等候"));

cb.await();//第三个同步点

} catch(Exception e) {

e.printStackTrace();

}

}

};

service.execute(runnable);

}

service.shutdown();

}

}

13.CountDownLatch

线程通过等待计数器归零来实现同步   实现一个人/多个人等待一个人/多个人的完成

public classCountdownLatchTest {public static voidmain(String[] args) {

ExecutorService service=Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1); //初始计数器的数为1

final CountDownLatch cdAnswer = new CountDownLatch(3);for (int i = 0; i < 3; i++) {

Runnable runnable= newRunnable() {public voidrun() {try{

System.out.println("线程" + Thread.currentThread().getName() + "准备接受执行命令");

cdOrder.await();

System.out.println("线程" + Thread.currentThread().getName() + "已接到命令, 开始执行");//模拟handling

Thread.sleep((long) (Math.random() * 5000));

System.out.println("线程" + Thread.currentThread().getName() + "的分任务完成");

cdAnswer.countDown();

}catch(Exception e) {

e.printStackTrace();

}

}

};

service.execute(runnable);

}try{

Thread.sleep((long) (Math.random() * 5000));

System.out.println("线程" + Thread.currentThread().getName() + "即将发送执行命令");

cdOrder.countDown();

System.out.println("线程" + Thread.currentThread().getName() + "已发送命令, 任务正在处理");

cdAnswer.await();

System.out.println("线程" + Thread.currentThread().getName() + "主管的所有任务完成");

}catch(Exception e) {

e.printStackTrace();

}

service.shutdown();

}

}

14. Exchanger

两个线程间互相交换数据

public classExchangerTest {public static voidmain(String[] args) {

ExecutorService service=Executors.newCachedThreadPool();final Exchanger exchanger = new Exchanger<>();

service.execute(newRunnable(){public voidrun() {try{

String data1= "王老吉";

System.out.println("线程" + Thread.currentThread().getName() + "正在把数据 " + data1 +" 换出去");

Thread.sleep((long)(Math.random()*2000));

String data2=(String)exchanger.exchange(data1);

System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为 " +data2);

}catch(Exception e){

e.printStackTrace();

}

}

});

service.execute(newRunnable(){public voidrun() {try{

String data1= "加多宝";

System.out.println("线程" + Thread.currentThread().getName() + "正在把数据 " + data1 +" 换出去");

Thread.sleep((long)(Math.random()*2000));

String data2=(String)exchanger.exchange(data1);

System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为 " +data2);

}catch(Exception e){

e.printStackTrace();

}

}

});

service.shutdown();

}

}

15. 阻塞队列

阻塞队列实现了BlockingQueue接口,  是生产者消费者模型的典范, 通过锁实现

put和take方法才具有阻塞功能

阻塞队列与线程同步      :  两个大小为1的空/满阻塞队列可以实现condition或wait/notify的效果

阻塞队列与Semaphore :  阻塞队列是一个线程存入数据, 一个线程取出数据; Semaphore一般用作同一线程获取和释放

public classBlockingQueueTest {public static voidmain(String[] args) {final BlockingQueue queue = new ArrayBlockingQueue<>(3);for (int i = 0; i < 2; i++) {newThread() {public voidrun() {while (true) {try{

Thread.sleep((long) (Math.random() * 1000));

System.out.println(Thread.currentThread().getName()+ "准备放数据!");

queue.put(1);

System.out.println(Thread.currentThread().getName()+ "已经放入数据, " + "队列目前有" + queue.size() + "个数据");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

}newThread() {public voidrun() {while (true) {try{

Thread.sleep(1000);

System.out.println(Thread.currentThread().getName()+ "准备取数据!");

queue.take();

System.out.println(Thread.currentThread().getName()+ "已经取走数据, " + "队列目前有" + queue.size() + "个数据");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

}

}

两个长度为1的空/满队列实现condition的效果

public classBlockingQueueImplSynchronization {public static voidmain(String[] args) {final Business business = newBusiness();new Thread(newRunnable() {

@Overridepublic voidrun() {for (int i = 1; i <= 20; i++) {

business.sub1(i);

}

}

}).start();for (int i = 1; i <= 20; i++) {

business.sub2(i);

}

}static classBusiness {

BlockingQueue queue1 = new ArrayBlockingQueue(1);

BlockingQueue queue2 = new ArrayBlockingQueue(1);

{try{

System.out.println("init");

queue2.put(1); //queue1为空 queue为满

} catch(InterruptedException e) {

e.printStackTrace();

}

}public void sub1(inti) {try{

queue1.put(1);

}catch(InterruptedException e) {

e.printStackTrace();

}for (int j = 1; j <= 10; j++) {

System.out.println("sub thread sequece of " + j + ", loop of " +i);

}try{

queue2.take();

}catch(InterruptedException e) {

e.printStackTrace();

}

}public void sub2(inti) {try{

queue2.put(1);

}catch(InterruptedException e1) {

e1.printStackTrace();

}for (int j = 1; j <= 20; j++) {

System.out.println("main thread sequece of " + j + ", loop of " +i);

}try{

queue1.take();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

16. 线程安全的非阻塞容器

并发集合

在JDK5之前, 多线程中对容器的操作部分需要手动加synchronized块保证线程安全

稍微轻便点的方式是使用Collections.synchronizedXXX()生成集合. 实现原理:通过装饰器模式在同名方法前添加synchronized(this), 来达到实现线程安全

但这是不完整的解决方案, 因为

1)装饰类的迭代器相关的代码没有加synchronized. 涉及到迭代还依然需要手动加synchronized块

2)迭代器遍历过程中除该迭代器外不能用其他方式增删元素(单线程在自身循环内, 多线程在不同线程执行不同部分), 否则抛出并发修改异常

3)最重要的, 并发低

//在集合的迭代器迭代过程中, 除了迭代器外不能对集合进行修改, 否则会抛出ConcurrentModificationException//ConcurrentModificationException的实现: 乐观锁, 记录一个版本号, 版本号不对抛异常

public classConcurrentModificationExceptionExample {public static voidmain(String[] args) {//Collection users = new CopyOnWriteArrayList();//若使用同步集合, 非迭代器修改就正常

Collection users = new ArrayList<>();

users.add(new User("张三", 28));

users.add(new User("李四", 25));

users.add(new User("王五", 31));

Iterator itrUsers=users.iterator();while(itrUsers.hasNext()) {

System.out.println("mark");

User user=(User) itrUsers.next();if ("张三".equals(user.getName())) {

users.remove(user);//非迭代器修改抛出异常//itrUsers.remove();//若使用迭代器修改, 则正常

} else{

System.out.println(user);

}

}

}

}

JDK5之后提出了很多线程安全的容器, 与前辈synchronized方式比起来, 它们的亮点并不是保证了线程安全, 而是它们在保证线程安全的同时尽量避免并发瓶颈

基本上限制条件多的容器都能实现Concurrent版本, 保持一定的读写并发;  像ArrayList LinkedList很难避开并发瓶颈, 退而求其次ArrayList实现了CopyOn保证了读并发;

LinkedList只能是通过Collections.synchronizedList()的synchronized方式(读|读都有锁), 尽量用其他集合替代.

ps:Collections.synchronizedList()或Vector的区别:  1.扩容量不同Vector 100%, SynchronizedList 50%.  2.Vector已对迭代器加锁, SynchronizedList需要手动加锁

原有集合

并发集合

原理

HashMap

ConcurrentHashMap

锁分段技术

HashSet

Collections.newSetFromMap(new ConcurrentHashMap())

用map版本实现

TreeMap

ConcurrentSkipListMap

用SkipList替代红黑树, CAS

TreeSet

ConcurrentSkipListSet

用map版本实现

Queue接口

ConcurrentLinkedQueue  非阻塞

CAS

ArrayList

CopyOnWriteArrayList

写时复制, 提高了读并发度;  以空间换取了部分写并发, 这点好坏需测试

Set接口

CopyOnWriteArraySet

用ArrayList版本实现, 用addIfAbsent()方法实现元素去重,写时还要复制, 因此写效率不佳

CAS原理类似乐观锁, 处理器保证底层实现, 理念:多次尝试肯定有一个能成(版本匹配则操作成功->该操作即具有原子性), 但会做很多无用功; 相比加锁能提高并发

17. 原子类

AtomicInteger等原子类用的是CAS, 并发比加锁高

实现多线程下安全性的要素:  原子性(不能被其他影响某变量的程序段打断) +  内存可见性 (一个线程修改, 另一个线程马上能看到)

synchronized: 实现了原子性和可见性

volatile: 实现内存可见性   CAS: 实现原子性

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值