1、JUC java.util.concurrent 并发编程工具类

  • java.util.concurrent
  • java.util.concurrent.atomic
  • java.util.concurrent.locks

1.1 、进程及线程

进程:操作系统中运行的每一个程序就是一个进程。
线程:是进程中的一条执行路径,一个进程中可以有多个线程。

1.2 、并发及并行

并发:多线程同一时间点访问同一个资源。
并行:同时进行多个事件,泡着脚打王者荣耀,美滋滋。。。

1.3 、高内聚低耦合

高内聚:系统的架构的完整尽可能少的依赖外部资源,单个系统的维护、运行等尽可能低的影响、依赖于外部其它系统。
低耦合:系统内部各个模块间的依赖关系尽可能的低,各个模块的维护的影响的范围小,整个系统的灵活性提高(系统的改变,即各个模块的增、删、改容易),降低系统的维护成本,能尽可能的提高系统的多功能性。系统变更成本低,具备实现多功能的条件。
一个好的系统应该是分成各个小块,分而治之的思想,把复杂问题分成小问题,逐个击破。每个小块应该是高内聚,小块之间应该是低耦合的。高内聚说的是这个小块的功能已经不可分割了,已经足够简单。耦合说的是这个小块依赖其他小块提供的功能,低就是少,弱,高耦合就是多,而且强。

1.4、 多线程买票

版本一

package com.mace.juc;/*** 资源类* * @author 10836**/
class Ticket {private int ticket = 30;public synchronized void saleTicket() {if (ticket > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "-正在售出:" + ticket-- + ",剩余:" + ticket);}}
}/*** 多线程售票* * @author 10836 线程 操作 资源类*/
public class SaleTicket {public static void main(String[] args) {Ticket t = new Ticket();new Thread(new Runnable() {@Overridepublic void run() {for (int x = 0; x < 40; x++) {t.saleTicket();}}}, "A").start();new Thread(new Runnable() {@Overridepublic void run() {for (int x = 0; x < 40; x++) {t.saleTicket();}}}, "B").start();new Thread(new Runnable() {@Overridepublic void run() {for (int x = 0; x < 40; x++) {t.saleTicket();}}}, "C").start();}
}

版本二

package com.mace.juc;import java.util.concurrent.locks.ReentrantLock;/*** 资源类* * @author 10836**/
class Ticket2 {private int ticket = 30;//可重入锁private final ReentrantLock lock = new ReentrantLock();public void saleTicket() {lock.lock();//加锁try {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "-正在售出:" + ticket-- + ",剩余:" + ticket);}} catch (Exception e) {e.printStackTrace();// TODO Auto-generated catch block}finally {lock.unlock();//解锁}}
}/*** 多线程售票* 使用可重入锁及lambda表达式* @author 10836 线程 操作 资源类*/
public class SaleTicket2 {public static void main(String[] args) {Ticket2 t = new Ticket2();//lambda表达式改写new Thread(()->{for (int x = 0; x < 40; x++) t.saleTicket();},"A").start();new Thread(()->{for (int x = 0; x < 40; x++) t.saleTicket();},"B").start();new Thread(()->{for (int x = 0; x < 40; x++) t.saleTicket();},"C").start();}
}

1.5、wait和sleep的区别

wait()方法会释放持有的锁,不然其他线程不能进入同步方法或同步块,从而不能调用notify(),notifyAll()方法来唤醒线程,产生死锁,所以释放锁,可以执行其他线程,也可以唤醒自己,只是设置停止自己的时间时不确定的;sleep方法不会释放持有的锁,设置sleep的时间是确定的会按时执行的;
sleep()必须指定时间,wait()可以指定时间也可以不指定;sleep()时间到,线程处于临时阻塞或运行状态;

1.6、线程的状态

NEW
实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。
RUNNABLE
实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。
调用线程的start()方法,此线程进入就绪状态。当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。锁池里的线程拿到对象锁后,进入就绪状态。
BLOCKED
阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
WAITING
处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。
TIMED_WAITING
处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。
TERMINATED
当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。这个线程对象也许是活的,但是它已经不是一个单独执行的线程。线程一旦终止了,就不能复生。在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

1.7、 lambda表达式

  • 接口中只有一个方法的声明(函数式接口@FunctionalInterface)
  • 拷贝小括号,写死右箭头,落地大括号。
  • 函数式接口中可以有多个default默认方法
  • 函数式接口中可以有多个static静态方法
package com.mace.lamdba;import java.util.UUID;/*** lambda表达式* @author 10836**/
@FunctionalInterface
interface Say{void sayGood(String name);default int count(int x,int y) {return x+y;}static String uuid() {return UUID.randomUUID().toString();}
}public class FirstLamdba {public static void main(String[] args) {Say s = (name)->{System.out.println(name +" say GOOD");};s.sayGood("bob");System.out.println(s.count(1, 2));System.out.println(Say.uuid());}
}

面向接口编程:
接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。接口是在一定粒度视图上同类事物的抽象表示。注意这里我强调了在一定粒度视图上,因为“同类事物”这个概念是相对的,它因为粒度视图不同而不同。在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类。“面向接口编程”中的接口是一种思想层面的用于实现多态性、提高软件灵活性和可维护性的架构部件,而具体语言中的“接口”是将这种思想中的部件具体实施到代码里的手段。
抽象类和接口的区别:
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果。
7、抽象类里可以没有抽象方法。
8、如果一个类里有抽象方法,那么这个类只能是抽象类。
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可继承接口,并可多继承接口,但类只能单根继承。

1.8、 线程间的通信

生产者消费者基础版

package com.mace.juc;
/*** 线程通信测试* @author 10836* 有两个线程,操作初始值为0的一个变量* 一个线程对该变量+1,一个线程对该变量-1,* 实现交替10轮,变量值仍为0;* * 高内聚低耦合 线程操作资源类*/
class AirCon{private int num = 0 ;//增加public synchronized void incr() throws InterruptedException {if(num != 0 ) {this.wait();}num++;System.out.println(Thread.currentThread().getName()+"-生产\t"+num);this.notifyAll();}//减少public synchronized void decr() throws InterruptedException {if(num ==0) {this.wait();}num--;System.out.println(Thread.currentThread().getName()+"-消费\t"+num);this.notifyAll();}
}public class ThreadNotfiyWait {public static void main(String[] args) {AirCon air = new AirCon();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.incr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"A").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.decr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"B").start();}
}

线程通信防止虚假唤醒

package com.mace.juc;/*** 线程通信测试* @author 10836* 有两个线程,操作初始值为0的一个变量* 一个线程对该变量+1,一个线程对该变量-1,* 实现交替10轮,变量值仍为0;* * 高内聚低耦合 线程操作资源类* 判断、通知、干活* 多线程交互中,必须防止多线程的虚假唤醒,也即(判断只能用while不能用if)* */class AirCon{private int num = 0 ;//增加public synchronized void incr() throws InterruptedException {while(num != 0 ) {this.wait();}num++;System.out.println(Thread.currentThread().getName()+"-生产\t"+num);this.notifyAll();}//减少public synchronized void decr() throws InterruptedException {while(num ==0) {this.wait();}num--;System.out.println(Thread.currentThread().getName()+"-消费\t"+num);this.notifyAll();}
}public class ThreadNotfiyWait {public static void main(String[] args) {AirCon air = new AirCon();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.incr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"A").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.incr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"B").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.decr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"C").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.decr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"D").start();}
}

线程通信新写法:

package com.mace.juc;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;/*** 线程通信测试-新写法* @author 10836* 有两个线程,操作初始值为0的一个变量* 一个线程对该变量+1,一个线程对该变量-1,* 实现交替10轮,变量值仍为0;* * 高内聚低耦合 线程操作资源类* 判断、通知、干活* 多线程交互中,必须防止多线程的虚假唤醒,也即(判断只能用while不能用if)* */class AirCon2{private int num = 0 ;private final ReentrantLock lock = new ReentrantLock(); private final Condition con = lock.newCondition();//增加public void incr() throws InterruptedException {lock.lock();try {while(num != 0 ) {//ifcon.await();//this.wait();}num++;System.out.println(Thread.currentThread().getName()+"-生产\t"+num);con.signalAll();//this.notifyAll();} finally {lock.unlock();}}//减少public void decr() throws InterruptedException {lock.lock();try {while(num ==0) {//ifcon.await();//this.wait();}num--;System.out.println(Thread.currentThread().getName()+"-消费\t"+num);con.signalAll();//this.notifyAll();} finally {lock.unlock();}}
}public class ThreadNotfiyWait2 {public static void main(String[] args) {AirCon2 air = new AirCon2();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.incr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"A").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.incr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"B").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.decr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"C").start();new Thread(()->{for(int i = 0 ; i < 10 ;i++) {try {air.decr();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}},"D").start();}
}

线程通信精确唤醒:

package com.mace.juc;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class PrintThread{private int flag = 1;//1=A 2=B 3=Cprivate final Lock lock = new ReentrantLock();//一道门 三把锁private final Condition con1 = lock.newCondition();private final Condition con2 = lock.newCondition();private final Condition con3 = lock.newCondition();public void print5() {lock.lock();try {while(flag != 1) {try {con1.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for(int i = 1 ; i <= 5;i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}flag = 2;con2.signal();} finally{lock.unlock();}}public void print10() {lock.lock();try {while(flag != 2) {try {con2.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for(int i = 1 ; i <= 10;i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}flag = 3;con3.signal();} finally{lock.unlock();}}public void print15() {lock.lock();try {while(flag != 3) {try {con3.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for(int i = 1 ; i <= 15;i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}flag = 1;con1.signal();} finally{lock.unlock();}}
}/*** 线程间通信精确通知* @author 10836* 多线程之间按顺序调用,实现A->B->C->三个线程启动:* * A 打印5次* B 打印10次* C 打印15次* 这样打印10轮。* * 高内聚低耦合 线程、操作、资源类* 判断、通知、干活* 多线程交互中,必须防止多线程的虚假唤醒,也即(判断只能用while不能用if)* 标志位*/
public class ThreadOrderAccess {public static void main(String[] args) {PrintThread pt = new PrintThread();new Thread(()->{for(int i = 0 ; i < 10 ; i++) {pt.print5();}},"A").start();new Thread(()->{for(int i = 0 ; i < 10 ; i++) {pt.print10();}},"B").start();new Thread(()->{for(int i = 0 ; i < 10 ; i++) {pt.print15();}},"C").start();}
}

2、锁



synchronized 实现同步:

  • 普通方法锁是当前实例对象
  • 静态方法锁是类的Class对象
  • 同步代码块是当前实例对象
package com.mace.juc;import java.util.concurrent.TimeUnit;class Phone{public synchronized void sendEmail() {System.out.println("send email。。。。");}public synchronized void sendSMS() {System.out.println("send SMS。。。。");}
}/*** lock机制* @author 10836**/
public class Lock {public static void main(String[] args) throws InterruptedException {Phone p = new Phone();new Thread(()->{p.sendEmail();},"A").start();TimeUnit.MILLISECONDS.sleep(100);new Thread(()->{p.sendSMS();},"A").start();}
}

3、list不安全

CopyOnWrite写时复制技术,是一种读写分离的思想,读写不同的容器。

package com.mace.collect;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;/*** ArrayList 是线程不安全的* @author 10836* java.util.ConcurrentModificationException并发修改异常* 导致原因:* 解决方案:*    1.Vector线程安全*  2.Collections.synchronizedList(new ArrayList<>())*  3.new CopyOnWriteArrayList<>()* 优化建议:使用线程安全容器*/
public class ThreadList {public static void main(String[] args) throws Exception {//List<String> list = new ArrayList<>();//List<String> list = new Vector<>();//List<String> list = Collections.synchronizedList(new ArrayList<>());List<String> list = new CopyOnWriteArrayList<String>(); //     CopyOnWriteArrayList源码
//      public boolean add(E e) {//          final ReentrantLock lock = this.lock;
//          lock.lock();
//          try {//              Object[] elements = getArray();
//              int len = elements.length;
//              Object[] newElements = Arrays.copyOf(elements, len + 1);复制
//              newElements[len] = e;
//              setArray(newElements);
//              return true;
//          } finally {//              lock.unlock();
//          }
//      }for(int i = 0 ; i < 30;i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0, 5));System.out.println(list);},String.valueOf(i)).start();}TimeUnit.SECONDS.sleep(5);System.out.println(list);}
}

4、set不安全

package com.mace.collect;import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;public class ThreadSet {public static void main(String[] args) {//Set<String> set =new HashSet<>();线程不安全//Set<String> set = Collections.synchronizedSet(new HashSet<>());Set<String> set = new CopyOnWriteArraySet<String>();for(int i = 0 ; i < 30;i++) {new Thread(()->{set.add(UUID.randomUUID().toString().substring(0, 5));System.out.println(set);},String.valueOf(i)).start();}}
}
//实际上是HashMap
public HashSet() {map = new HashMap<>();
}
//添加的值存储在HashMap的key,HashMap的value为new Object()
public boolean add(E e) {return map.put(e, PRESENT)==null;//private static final Object PRESENT = new Object();
}

5、map不安全

package com.mace.collect;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class ThreadMap {public static void main(String[] args) {//HashMap<String,String> map = new HashMap<>();//Map<Object, Object> map = Collections.synchronizedMap(new HashMap<Object,Object>());Map<Object, Object> map = new ConcurrentHashMap<Object, Object>();for(int i = 0 ; i < 30;i++) {new Thread(()->{map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0, 5));System.out.println(map);},String.valueOf(i)).start();}}
}

6、callable创建线程

package com.mace.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/*** callable创建多线程* @author 10836*/
class MyThread implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println(Thread.currentThread().getName());return 1;}
}public class CallableThread {public static void main(String[] args) throws Exception {FutureTask<Integer> task = new FutureTask<>(new MyThread());new Thread(task, "A").start();System.out.println(task.get());}
}

6.1 callable与runable的区别

  • 是否有返回值
  • 是否抛异常
  • 落地方法call和run

6.2 callable细节

  • get方法一般放在最后一行,否则将等待直到有返回值。
  • 多个线程同时调用FutureTask,首次得到返回值会进行缓存,其他线程不在重新调用。

7、多线程辅助工具类

7.1 、CountDownLatch加计数器

package com.mace.thread;import java.util.concurrent.CountDownLatch;/*** 主线程必须等到其他线程全部执行完再结束* @author 10836*/
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {/*** 当一个线程或多线程调用await方法时,线程会阻塞。* 其他线程调用countDown方法会将计数器减一。* 当计数器为0时,因await方法阻塞的线程会被唤醒,继续执行。*/CountDownLatch latch = new CountDownLatch(6);for (int i = 0; i < 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName()+"\t离开教室...");latch.countDown();},String.valueOf(i)).start();}latch.await();System.out.println("班长离开教室...");}
}

7.2、CyclicBarrier减计数器

package com.mace.thread;import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;/*** 减法计数器* @author 10836*/
public class CyclicBarrierDemo {public static void main(String[] args) {// public CyclicBarrier(int parties, Runnable barrierAction) CyclicBarrier cb = new CyclicBarrier(7,()->{System.out.println("**召唤神龙**");});for (int i = 1; i < 8; i++) {final int temp = i;new Thread(()->{System.out.println("收集到"+temp+"龙珠...");try {cb.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (BrokenBarrierException e) {// TODO Auto-generated catch blocke.printStackTrace();}},String.valueOf(i)).start();}}
}

7.3、Semaphore信号量

package com.mace.thread;import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;/*** 信号量控制* @author 10836* 6辆车停3个车位上*/
public class SemaphoreDemo {public static void main(String[] args) {/*** acquire(获取)当一个线程调用acquire操作时,它要么成功的获取信号量(信号量减一)* 要么一直等下去,直到有线程释放信号量,或超时。* release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。* 目的:*  1.多个共享资源的互斥使用*  2.并发线程数的控制*/Semaphore sp = new Semaphore(3);//三个车位for (int i = 1; i < 7; i++) {new Thread(()->{try {sp.acquire();//占住车位System.out.println(Thread.currentThread().getName()+"号车,停入车位。");TimeUnit.SECONDS.sleep(5);System.out.println(Thread.currentThread().getName()+"号车,驶离车位。");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {sp.release();//释放车位}},String.valueOf(i)).start();}}
}

7.4 、ReadWriteLock读写锁

package com.mace.thread;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;class MyCache{private volatile Map<String,String> map = new HashMap<>();private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void set(String key,String value) {lock.writeLock().lock();try {System.out.println(Thread.currentThread().getName()+"\t开始写入:"+key);map.put(key, value);TimeUnit.MILLISECONDS.sleep(500);System.out.println(Thread.currentThread().getName()+"\t写入成功");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.writeLock().unlock();}}public void get(String key) {lock.readLock().lock();try {System.out.println(Thread.currentThread().getName()+"\t开始读取");map.get(key);TimeUnit.MILLISECONDS.sleep(500);System.out.println(Thread.currentThread().getName()+"\t读取成功");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.readLock().unlock();}}}/*** 多个线程同时读取一个资源类没有问题,所以为了满足并发量,* 读取共享资源可以同时进行。但是为了满足数据的一致性,写* 共享资源时就不应该再有其他线程可以对资源进行读或写。*   1.读-读能共存*   2.读-写不能共存*   3.写-写不能共存*/
public class ReadWriteLcok {public static void main(String[] args) {MyCache cache = new MyCache();for (int i = 1; i < 6; i++) {final int temp = i;new Thread(()->{cache.set(String.valueOf(temp), String.valueOf(temp));},String.valueOf(i)).start();}for (int i = 1; i < 6; i++) {final int temp = i;new Thread(()->{cache.get(String.valueOf(temp));},String.valueOf(i)).start();}}
}

8、BlockingQueue阻塞队列

必须要阻塞/不得不阻塞, FIFO (first-in-first-out) 。

  • 当队列是空的,从队列中获取元素的操作会被阻塞。
  • 当队列是满的,往队列中添加元素的操作会被阻塞。

阻塞队列类型

主要方法:

package com.mace.thread;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;/*** 阻塞队列* @author 10836*/
public class BlockQueueDemo {public static void main(String[] args) {BlockingQueue<String> queue = new ArrayBlockingQueue<String>(3);System.out.println(queue.add("A"));System.out.println(queue.add("B"));System.out.println(queue.add("C"));System.out.println(queue.remove());System.out.println(queue.remove());System.out.println(queue.remove());//java.util.NoSuchElementException 超出容量后抛出异常System.out.println(queue.remove());}
}

9、线程池

9.1、线程池的优势


(1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
(2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
(3)提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

9.2、使用

package com.mace.threadpool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;/*** 线程池* @author 10836**/
public class ThreadPool {public static void main(String[] args) throws InterruptedException {//ExecutorService pool = Executors.newFixedThreadPool(5);//固定线程数//ExecutorService pool = Executors.newSingleThreadExecutor();//只有一个线程ExecutorService pool = Executors.newCachedThreadPool();//只有一个线程for(int i = 1 ; i < 11;i++) {final Integer temp = i;pool.execute(()->{System.out.println(Thread.currentThread().getName()+"处理第"+temp+"顾客。。。");});//TimeUnit.SECONDS.sleep(1);}}
}

9.3、线程池参数

/*   corePoolSize:线程池中的常驻核心线程数maximumPoolSize:线程池中能够容纳同时执行的最大线程数,此值必须大于1.keepAliveTime:多余的空闲线程的存活时间,超过corePoolSize的线程,将在keepAliveTime到达时销毁。unit:keepAliveTime的时间单位。workQueue:任务队列,被提交但尚未被执行的任务。threadFactory:生产线程中工作线程的线程工厂,一般默认即可。handler:拒绝策略,当队列满了,并且工作线程大于等于线程池的maximumPoolSize时如何拒绝请求执行的策略。public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}
*/

9.4、线程池工作原理


9.5、线程池的拒绝策略

    new ThreadPoolExecutor.AbortPolicy():抛出异常RejectedExecutionExceptionnew ThreadPoolExecutor.CallerRunsPolicy():将任务返回给调用者new ThreadPoolExecutor.DiscardPolicy():丢弃无法处理的任务new ThreadPoolExecutor.DiscardOldestPolicy():丢弃队列中等待最久的任务

9.6、线程池参数优化设计

  • cpu密集型
  • io密集型

10、函数式接口

package com.mace.lamdba;import java.util.function.Consumer;/*** 函数式接口测试* @author 狼牙*/
public class FunctionInterFaceDemo {public static void main(String[] args) {//      Consumer<String> comsumer = new Consumer<String>() {//          @Override
//          public void accept(String t) {//          }
//      };//消费型接口,有输入没有返回值。Consumer<String> comsumer = (t)->{System.out.println(t);};comsumer.accept("JAVA");}
}

11、stream流式编程

package com.mace.stream;import java.util.Arrays;
import java.util.List;/*** stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。* 集合讲的是数据,流将的是计算。* 特点:*   1.自己不会存储元素*  2.不会改变源对象,会返回一个持有结果的新stream*  3.stream操作是延迟执行的,需要结果的时候才执行。* 操作:*  1.创建一个数据源*  2.中间操作,处理数据源*  3.终止操作,执行中间操作链,产生结果。* @author 狼牙**/class User{private String name;private int age;public User(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + "]";}
}public class StreamDemo {public static void main(String[] args) {User u1 = new User("a",18);User u2 = new User("b",22);User u3 = new User("c",29);List<User> list = Arrays.asList(u1,u2,u3);list.stream().map(u->{return u.getName().toUpperCase();}).forEach(System.out::println);}
}

12、ForkJoin框架

package com.mace.forkjoin;
/*** 分支合并框架* @author 狼牙* ForkJoinPool* ForkJoinTask抽象类 -> RecursiveTask实现类*/import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;/*** 计算0-100的和* @author 10836**/
class MyTask extends RecursiveTask<Integer>{private static final int FLAG = 10;private int start;private int end;private int result;public MyTask(int start, int end) {super();this.start = start;this.end = end;}@Overrideprotected Integer compute() {if((end-start) <= FLAG) {for(int i = start;i<=end;i++) {result = result + i;}}else {//如果小于10继续拆分int middle = (start + end)/2;MyTask m1 = new MyTask(start,middle);MyTask m2 = new MyTask(middle+1,end);m1.fork();m2.fork();Integer j1 = m1.join();Integer j2 = m2.join();result = j1+j2;}return result;}
}public class ForkJoinDemo {public static void main(String[] args) throws Exception {ForkJoinPool pool = new ForkJoinPool();ForkJoinTask<Integer> task = pool.submit(new MyTask(0, 100));System.out.println(task.get());pool.shutdown();}
}

12.1、异步回调

package com.mace.forkjoin;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;/*** 异步回调* @author 10836*/
public class CompleTableFutureDemo {public static void main(String[] args) throws Exception {CompletableFuture<Void> future = CompletableFuture.runAsync(()->{System.out.println("异步操作没有返回值...");});future.get();//调用get方法才会执行CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(()->{System.out.println("异步操作,有返回值....");//int x = 1/0;return 666;});Integer integer = supplyAsync.whenComplete((t,u)->{//当异步任务正常执行,t为任务的返回值,u为异常对象,为null。//当异步任务出现异常,则t为null,u为异常对象。System.out.println("**"+t);System.out.println("--"+u);}).exceptionally((t)->{//当异步任务正常执行,次方法不会被调用。//当异步任务出现异常,t为异常对象,并且有返回值。System.out.println("++"+t);return 999;}).get();System.out.println(integer);}
}

JUC并发编程 第一季相关推荐

  1. ❤️《JUC并发编程从入门到高级》(建议收藏)❤️

    JUC并发编程 1.什么是JUC JUC的意思就是java并发编程工具包,与JUC相关的有三个包:java.util.concurrent.java.util.concurrent.atomic.ja ...

  2. 基于《狂神说Java》JUC并发编程--学习笔记

    前言: 本笔记仅做学习与复习使用,不存在刻意抄袭. -------------------------------------------------------------------------- ...

  3. Java JUC并发编程详解

    Java JUC并发编程详解 1. JUC概述 1.1 JUC简介 1.2 进程与线程 1.2 并发与并行 1.3 用户线程和守护线程 2. Lock接口 2.1 Synchronized 2.2 什 ...

  4. 多线程进阶=》JUC并发编程

    多线程进阶=>JUC并发编程 1.什么是JUC ​ JUC是java.util.concurrent的简写. ​ 用中文概括一下,JUC的意思就是java并发编程工具包. ​ 并发编程的本质就是 ...

  5. 爬梯:JUC并发编程(三)

    学习资源整理自:B站<狂神说> 书接上回 JUC并发编程 12.CompletableFuture 异步回调 理解 父类:Future,对将来的某个事件的结果进行建模 可以用ajax进行理 ...

  6. 爬梯:JUC并发编程(二)

    学习资源整理自:B站<狂神说> 书接上回 JUC并发编程 8.线程池(重点) 线程池:三大方法.七大参数.四种拒绝策略 池化技术 程序的执行,本质:占用系统的资源!优化资源的使用==> ...

  7. 【尚硅谷】大厂必备技术之JUC并发编程——笔记总结

    [JUC并发编程01]JUC概述 关键字:进程和线程.进程和线程.wait和sleep.并发与并行.管程.用户线程和守护线程 [JUC并发编程02]Lock接口 关键字:synchronized.Lo ...

  8. JUC并发编程中的集合不安全问题源码解析

    JUC并发编程四:集合不安全(Java) 1.List不安全! 代码示例: package unsafe;import java.util.*; import java.util.concurrent ...

  9. 厚积薄发打卡Day26:狂神说Java之JUC并发编程<代码+笔记>(上)

    前言: 学习视频来源:[狂神说Java]JUC并发编程最新版通俗易懂 一个十分优秀且励志的技术大牛+Java讲师,十分推荐他的频道:遇见狂神说

最新文章

  1. 配置Fedora15 x86_32
  2. OpenCV Python教程(3)(4)(5): 直方图的计算与显示 形态学处理 初级滤波内
  3. java sftp 实例_JAVA实现SFTP的实例
  4. Android-用ListView显示SDCard文件列表
  5. kafka经典面试题
  6. python自学笔记_Python 自学笔记
  7. 深入了解C++的广泛应用
  8. 天宇优配|利好太多,写不下了!A股港股全线走高,股民嗨了
  9. 2022年低压电工考试题及在线模拟考试
  10. Python实现十大排序算法
  11. Oracle 锁表查询大全
  12. android:scheme 常用类型,android scheme
  13. 07_LTP语言技术平台
  14. 360插件化Replugin爬坑之路
  15. mysql 中添加和删除字段
  16. 林期苏曼属性标签编辑_标签设计软件如何设置条码文字分段显示
  17. 在后台定时连续截屏的工具 —— 定时执行专家
  18. CAD 随机卵石混凝土 混凝土细观 卵石混凝土模型
  19. 如何利用金山云ARM云服务器搭建Nginx服务
  20. 3l如何使用_家装时如何对低水压Say No?不难,教你一招让水源滚滚而来

热门文章

  1. 手机地图哪个好?从老虎地图说开去(转帖)
  2. 老赵书托(2):计算机程序的构造与解释
  3. 京东获取cookie教程
  4. python制作热图folium_Python Folium包可以在热图上绘制标记吗?
  5. Windows Server 2019 AD域控搭建
  6. 交易模型的定义及理论基础
  7. python读取文本两个数字的成语_【十分钟Python知识点】让文本数据更加生动——词云工具推荐...
  8. win10系统 Docker 安装和配置
  9. Ptrace调试ARM架构多线程
  10. 《民国奇探》的弹幕有点逗比,用 Python 爬下来看看