如果您有任何疑问,可以在下面询问或输入您要寻找的!
狂神说JUCbilbil视频链接详细地址:https://www.bilibili.com/video/BV1B7411L7tE
JUC便是 java.util
下的工具箱、包、归类等。
一般的进程编码:
Thread
Runnable 沒有传参、高效率对比入 Callable 相对性较低!
Callable 有传参!
进程、过程,假如不可以应用一句话说出来的技术性,不扎扎实实!
过程:一个程序流程,QQ.exe Music.exe 程序流程的结合;
一个过程通常能够包括好几个进程,最少包括一个!
Java默认设置有两个进程? mian、GC
进程:开过一个过程 Typora,写毛笔字,全自动储存(进程承担的)
针对Java来讲出示了:Thread、Runnable、Callable
实际操作进程。
Java 确实能够打开进程吗? 回答是:开不上的!
public synchronized void start() {
/**
* This method is not invoked for the main method thread
* or "system" group threads created/set up by the VM. Any new
* functionality added to this method in the future may have to
* also be added to the VM.A zero status value corresponds to
* state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/*
* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented.
*/
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
// 当地方式,最底层实际操作的是C++ ,Java 没法立即实际操作硬件配置
private native void start0();
高并发、并行处理
并发编程:高并发、并行处理
高并发(线程同步实际操作同一个資源)
并行处理(多本人一起走动)
public class Test1 {
public static void main(String[] args) {
// 获得cpu的核数
// CPU 密集式,IO密集式
System.out.println(Runtime.getRuntime().availableProcessors());
// 假如电脑上是8核,则結果輸出8
}
}
并发编程的实质:灵活运用CPU的資源
进程几个情况(6个)
public enum State {
/**
* Thread state for a thread which has not yet started.
* 进程新生儿情况
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
* 进程运作中
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
* 进程阻塞状态
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
*
* - {@link Object#wait() Object.wait} with no timeout
* - {@link #join() Thread.join} with no timeout
* - {@link LockSupport#park() LockSupport.park}
*
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called Object.wait()
* on an object is waiting for another thread to call
* Object.notify() or Object.notifyAll() on
* that object. A thread that has called Thread.join()
* is waiting for a specified thread to terminate.
* 进程等候情况,死等
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
*
* - {@link #sleep Thread.sleep}
* - {@link Object#wait(long) Object.wait} with timeout
* - {@link #join(long) Thread.join} with timeout
* - {@link LockSupport#parkNanos LockSupport.parkNanos}
* - {@link LockSupport#parkUntil LockSupport.parkUntil}
*
* 进程请求超时等候情况,超出一定時间就不会再等
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
* 进程停止情况,意味着进程实行结束
*/
TERMINATED;
}
wait/sleep 差别
1、二者来源于不一样的类
2、有关锁的释放出来
3、应用的范畴是不一样的
传统式 Synchronized锁
看来一个线程同步售票事例
package com.haust.juc01;
/*
* @Auther: csp1999
* @Date: 2020/07/21/13:59
* @Description: 售票事例
*/
public class SaleTicketTDemo01 {
/*
* 真实的线程同步开发设计,企业中的开发设计,减少耦合度
* 进程便是一个独立的資源类,沒有一切附设的实际操作!
* 1、 特性、方式
*/
public static void main(String[] args) {
//高并发:好几个进程另外实际操作一个資源类,把資源类丢进进程
Ticket ticket = new Ticket();
// @FunctionalInterface 函数式接口,jdk1.8 lambada关系式
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "C").start();
}
}
//資源类 OOP
class Ticket {
//特性、方式
private int number = 50;
// 售票的方法
// synchronized 实质: 序列,锁
public synchronized void sale() {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "售出了" +
(50-(--number)) + "张票,剩下:" + number + "张票");
}
}
}
Lock 插口
公平公正锁:十分公平公正,进程实行次序依照先来后到次序
非公平公正锁:十分不合理:能够排队 (默认设置锁)
将上边的售票事例用lock锁 更换synchronized:
package com.haust.juc01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* @Auther: csp1999
* @Date: 2020/07/21/13:59
* @Description: 售票事例2
*/
public class SaleTicketTDemo02 {
public static void main(String[] args) {
//高并发:好几个进程另外实际操作一个資源类,把資源类丢进进程
Ticket2 ticket = new Ticket2();
// @FunctionalInterface 函数式接口,jdk1.8 lambada关系式
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) {
ticket.sale();
}
}, "C").start();
}
}
//Lock 3流程
// 1. new ReentrantLock();
// 2. lock.lock() 上锁
// 3. lock.unlock() 开启
class Ticket2 {
//特性、方式
private int number = 50;
Lock lock = new ReentrantLock();
// 售票方法
public void sale() {
lock.lock();// 上锁
try {
// 业务流程编码
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "售出了" +
(50 - (--number)) + "张票,剩下:" + number + "张票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();// 开启
}
}
}
Synchronized 和 Lock 差别:
1、Synchronized 内嵌的Java关键词, Lock 是一个Java类
2、Synchronized 没法分辨获得锁的情况,Lock 能够分辨是不是获得到锁
3、Synchronized 会全自动释放出来锁,lock 务必要手动式释放出来锁!如果不释放出来锁,死锁
4、Synchronized 进程 1(得到锁,假如进程1堵塞)、进程2(等候,傻乎乎等);Lock锁也不一定会等候下来;
5、Synchronized 可重入锁,不能终断的,非公平公正;Lock ,可重入锁,能够分辨锁,非公平公正(能够自身设定);
6、Synchronized 合适锁小量的编码同歩难题,Lock 合适锁很多的同歩编码!
锁是啥,怎么知道锁的是啥!
这个问题在以后会举例说明剖析。
招聘面试常见的难题:单例模式、快速排序算法、经营者和顾客、死锁
经营者和顾客难题 Synchronized 版
package com.haust.pc;
/**
* 进程中间的通讯难题:经营者和顾客难题! 等候唤起,通告唤起
* 进程更替实行 A B 实际操作同一个自变量 num = 0
* A num+1
* B num-1
*/
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try { data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
// 分辨等候,业务流程,通告
class Data { // 数据 資源类
private int number = 0;
//+1
public synchronized void increment() throws InterruptedException {
/*
假定 number这时相当于1,即早已被生产制造了商品
假如这儿用的是if分辨,假如这时A,C2个经营者进程角逐increment()方式执行权
假定A取得执行权,历经分辨number!=0创立,则A.wait()逐渐等候(wait()会释放出来锁),随后C尝试去实行
生产制造方式,但仍然分辨number!=0创立,则B.wait()逐渐等候(wait()会释放出来锁)
恰巧此刻顾客进程进程B/D去消費了一个商品,使number=0随后,B/D消費完后启用this.notifyAll();
此刻两个准备中的经营者进程再次生产制造商品,而这时number++ 实行了2次
同样,反复所述全过程,经营者进程再次wait()等候,顾客启用this.notifyAll();
随后经营者再次超前的生产制造,最后造成 ‘生产过剩’,即number大于1
if(number != 0){
// 等候
this.wait();
}*/
while (number != 0) { // 留意这儿不能用if 不然会发生虚报唤起难题,解决方案将if换为while
// 等候
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>" + number);
// 通告别的进程,我+1结束了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number == 0) {
// 等候
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "=>" + number);
// 通告别的进程,我-1结束了
this.notifyAll();
}
}
难题存有,A B C D 4 个进程! 虚报唤起
最先到CHM 官方网文本文档 java.lang包下 寻找Object ,随后寻找wait()方式:
因而所述编码中务必应用while分辨,而不可以应用if
JUC版的经营者和顾客难题
官方网文本文档中根据Lock 寻找 Condition
点进Condition 查询
编码完成:
package com.haust.pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 进程中间的通讯难题:经营者和顾客难题! 等候唤起,通告唤起
* 进程更替实行 A B 实际操作同一个自变量 num = 0
* A num+1
* B num-1
*/
public class B {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
// 分辨等候,业务流程,通告
class Data2 { // 数据 資源类
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//condition.await(); // 等候
//condition.signalAll(); // 唤起所有
//+1
public void increment() throws InterruptedException {
lock.lock();
try {
// 业务流程编码
while (number != 0) {
// 等候
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "=>" + number);
// 通告别的进程,我+1结束了
condition.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
//-1
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number == 0) {
// 等候
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + "=>" + number);
// 通告别的进程,我-1结束了
condition.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
一切一个新的技术性,肯定并不是只不过是遮盖了原先的技术性,是有其对旧技术性的优点和填补!
Condition 精确的通告和唤起进程
所述程序执行結果如图所示:
难题:ABCD进程 占领实行的次序是任意的,假如想让ABCD进程井然有序实行,该怎样改善编码?
编码完成:
package com.haust.pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* A 实行完启用B,B实行完启用C,C实行完启用A
*/
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.printA();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.printB();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.printC();
}
}, "C").start();
}
}
class Data3 { // 資源类 Lock
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1;
// number=1 A实行 number=2 B实行 number=3 C实行
public void printA() {
lock.lock();
try {
// 业务流程,分辨-> 实行-> 通告
while (number != 1) {
// A等候
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "=>AAAAAAA");
// 唤起,唤起特定的人,B
number = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() {
lock.lock();
try {
// 业务流程,分辨-> 实行-> 通告
while (number != 2) {
// B等候
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB");
// 唤起,唤起特定的人,c
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC() {
lock.lock();
try {
// 业务流程,分辨-> 实行-> 通告
// 业务流程,分辨-> 实行-> 通告
while (number != 3) {
// C等候
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "=>CCCCC ");
// 唤起,唤起特定的人,A
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
检测結果:
前边明确提出一个难题:怎么知道锁的到底是谁!了解什么叫锁,锁究竟锁的到底是谁!
深刻领会大家的锁
synchronized 锁的目标是方式的调用者
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/**
* 8锁,便是有关锁的八个难题
* 1、规范状况下,2个进程先复印 发信息還是 先复印 通电话? 1/发信息 2/通电话
* 1、sendSms延迟时间4秒,2个进程先复印 发信息還是 通电话? 1/发信息 2/通电话
*/.
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
// 锁的存有
new Thread(()->{
phone.sendSms();
},"A").start();
// 捕捉
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
// synchronized 锁的目标是方式的调用者!、
// 2个方式用的是同一个目标启用(同一个锁),谁先取得锁谁实行!
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);// 怀着锁睡眠质量
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public synchronized void call(){
System.out.println("通电话");
}
}
// 先实行 发信息,后实行通电话
一般方式沒有锁!并不是同歩方式,也不受锁的危害,一切正常实行
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/**
* 3、 提升了一个一般方式后!先实行发信息還是Hello?// 一般方式
* 4、 2个目标,2个同歩方式, 发信息還是 通电话? // 通电话
*/
public class Test2 {
public static void main(String[] args) {
// 2个目标,2个调用者,俩把锁!
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
//锁的存有
new Thread(()->{
phone1.sendSms();
},"A").start();
// 捕捉
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
new Thread(()->{
phone2.hello();
},"C").start();
}
}
class Phone2{
// synchronized 锁的目标是方式的调用者!
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发信息");
}
public synchronized void call(){
System.out.println("通电话");
}
// 这儿沒有锁!并不是同歩方式,不会受到锁的危害
public void hello(){
System.out.println("hello");
}
}
// 先实行通电话,然后实行hello,最终实行发信息
**不一样案例目标的Class类模板只有一个,static静态数据的同歩方式,锁的是Class **
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/**
* 5、提升2个静态数据的同歩方式,只有一个目标,先复印 发信息?通电话?
* 6、2个目标!提升2个静态数据的同歩方式, 先复印 发信息?通电话?
*/
public class Test3 {
public static void main(String[] args) {
// 2个目标的Class类模板只有一个,static,锁的是Class
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
//锁的存有
new Thread(()->{
phone1.sendSms();
},"A").start();
// 捕捉
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3唯一的一个 Class 目标
class Phone3{
// synchronized 锁的目标是方式的调用者!
// static 静态方法
// 类一载入就拥有!锁的是Class
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println("发信息");
}
public static synchronized void call(){
System.out.println("通电话");
}
}
// 先实行发信息,后实行通电话
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/**
* 7、一个静态数据的同歩方式,一个一般的同歩方式 ,一个目标,先复印 发信息?通电话?
* 8、一个静态数据的同歩方式,一个一般的同歩方式 ,2个目标,先复印 发信息?通电话?
*/
public class Test4 {
public static void main(String[] args) {
// 2个目标的Class类模板只有一个,static,锁的是Class
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
//锁的存有
new Thread(()->{
phone1.sendSms();
},"A").start();
// 捕捉
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3唯一的一个 Class 目标
class Phone4{
// 静态数据的同歩方式 锁的是 Class 类模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发信息");
}
// 一般的同歩方式 锁的调用者(目标),二者锁的目标不一样,因此 不用等候
public synchronized void call(){
System.out.println("通电话");
}
}
// 7/8 二种状况下,全是先实行通电话,后实行发信息,由于二者锁的目标不一样,
// 静态数据同歩方式锁的是Class类模板,一般同歩方式锁的是实例化的目标,
// 因此 无需等候前面一种开启后 后面一种才可以实行,只是二者并行执行,由于发信息休眠状态4s
// 因此 通电话先实行。
总结
List 不安全
**List、ArrayList 等在高并发线程同步标准下,不可以完成信息共享,好几个进程另外启用一个list目标情况下便会发生高并发改动出现异常ConcurrentModificationException **。
编码举例说明:
package com.haust.unsafe;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
// java.util.ConcurrentModificationException 高并发改动出现异常!
public class ListTest {
public static void main(String[] args) {
// 高并发下 ArrayList 不安全的吗,Synchronized;
/*
* 解决方法;
* 计划方案1、List list = new Vector<>();
* 计划方案2、List list =
* Collections.synchronizedList(new ArrayList<>());
* 计划方案3、List list = new CopyOnWriteArrayList<>();
*/
/* CopyOnWrite 载入时拷贝 COW 电子计算机编程设计行业的一种优化策略;
* 好几个进程启用的情况下,list,载入的情况下,固定不动的,载入(遮盖)
* 在载入的情况下防止遮盖,导致数据信息难题!
* 读写分离
* CopyOnWriteArrayList 比 Vector Nb 在哪儿?
*/
List list = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
CopyOnWriteArrayList源代码剖析参照
Set 不安全
**Set、Hash 等在高并发线程同步标准下,不可以完成信息共享,好几个进程另外启用一个set目标情况下便会发生高并发改动出现异常ConcurrentModificationException **。
编码举例说明:
package com.haust.unsafe;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* 同理可证 : ConcurrentModificationException 高并发改动出现异常
* 1、Set set =
* Collections.synchronizedSet(new HashSet<>());
* 2、
*/
public class SetTest {
public static void main(String[] args) {
//Set set = new HashSet<>();//不安全
// Set set = Collections.synchronizedSet(new HashSet<>());//安全性
Set set = new CopyOnWriteArraySet<>();//安全性
for (int i = 1; i <=30 ; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
拓展:hashSet 最底层是啥?
能够看得出 HashSet 的最底层便是一个HashMap
HashMap源代码剖析参照
Map 不安全
回望Map操作过程:
编码举例说明:
package com.haust.unsafe;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
// ConcurrentModificationException
public class MapTest {
public static void main(String[] args) {
// map 是那样用的吗? 并不是,工作上无需 HashMap
// 默认设置等额的于哪些? new HashMap<>(16,0.75);
// Map map = new HashMap<>();
// 拓展:科学研究ConcurrentHashMap的基本原理
Map map = new ConcurrentHashMap<>();
for (int i = 1; i <=30; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(),
UUID.randomUUID().toString().substring(0,5));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}
Callable 和 Runable 比照:
举例说明:例如Callable 就是你自身,你要根据你的女友 **Runable **了解她的好闺蜜 Thread
一样的 Lock 和 Synchronized 二者的差别,前面一种是java.util 下的插口 后面一种是 java.lang 下的关键词。
编码举例说明
package com.haust.callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 1、研究基本原理
* 2、觉自身会用
*/
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// new Thread(new Runnable()).start();// 运行Runnable
// new Thread(new FutureTask()).start();
// new Thread(new FutureTask( Callable )).start();
new Thread().start(); // 怎么启动Callable?
// new 一个MyThread案例
MyThread thread = new MyThread();
// MyThread案例放进FutureTask
FutureTask futureTask = new FutureTask(thread); // 兼容类
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); // call()方式結果会被缓存文件,提高工作效率,因而只复印一个call
// 这一get 方式很有可能会造成堵塞!把他放进最终
Integer o = (Integer) futureTask.get();
// 或是应用异步通信来解决!
System.out.println(o);// 1024
}
}
class MyThread implements Callable {
@Override
public Integer call() {
System.out.println("call()"); // A,B2个进程会复印好多个call?(一个)
// 用时的实际操作
return 1024;
}
}
//class MyThread implements Runnable {
//
// @Override
// public void run() {
// System.out.println("run()"); // 会复印好多个run
// }
//}
关键点:
1、有缓存文件
2、結果很有可能必须等候,会堵塞!
加减法电子计数器: 完成启用几回进程后 再开启某一个每日任务
编码举例说明:
package com.haust.add;
import java.util.concurrent.CountDownLatch;
// 电子计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
// 数量是6,务必要执行任务的情况下,再应用!
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()
+" Go out");
countDownLatch.countDown(); // 总数-1
},String.valueOf(i)).start();
}
countDownLatch.await(); // 等候电子计数器归零,随后再往下实行
System.out.println("Close Door");
}
}
基本原理:
countDownLatch.countDown();
// 总数-1
countDownLatch.await();
// 等候电子计数器归零,随后再往下实行
每一次有进程启用 countDown() 总数-1,假定电子计数器变成0,countDownLatch.await() 便会被唤起,执行!
加减法电子计数器:集满7颗七龙珠开宝箱
编码举例说明:
package com.haust.add;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
/*
* 集满7颗七龙珠开宝箱
*/
// 招唤七龙珠的进程
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("开宝箱取得成功!");
});
for (int i = 1; i <=7 ; i++) {
final int temp = i;
// lambda能实际操作到 i 吗
new Thread(()->{
System.out.println(Thread.currentThread().getName()
+"搜集"+temp+"个七龙珠");
try {
cyclicBarrier.await(); // 等候
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
Semaphore:信号量
过流保护/抢车位!6车—3个泊车部位
编码举例说明:
package com.haust.add;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main(String[] args) {
// 进程总数:停车场! 过流保护!、
// 假如现有3个进程实行(3个停车位已满),则别的进程必须等候‘停车位’释放出来后,才可以实行!
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
// acquire() 获得
try {
semaphore.acquire();
System.out.println(Thread.currentThread()
.getName()+"抢到停车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread()
.getName()+"离去停车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // release() 释放出来
}
},String.valueOf(i)).start();
}
}
}
仅有三个停车位,仅有当某一辆车离去停车位,停车位空出去后,下一辆车才可以在这里停车。
輸出結果如图所示:
基本原理:
semaphore.acquire();
得到,假定假如早已满了,等候,等候被释放出来截止!semaphore.release();
释放出来,会将当今的信号量释放出来 + 1,随后唤起等候的进程!
功效: 好几个资源共享相互独立的应用!高并发过流保护,操纵较大 的线程数!
ReadWriteLock
编码举例说明:
package com.haust.rw;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 独享锁(写锁) 一次只有被一个进程占据
* 共享资源锁(读锁) 好几个进程能够另外占据
* ReadWriteLock
* 读-读 能够并存!
* 读-写 不可以并存!
* 写-写 不可以并存!
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
//MyCache myCache = new MyCache();
MyCacheLock myCacheLock = new MyCacheLock();
// 载入
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
// 载入
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.get(temp+"");
},String.valueOf(i)).start();
}
}
}
/**
* 自定缓存文件
* 上锁的
*/
class MyCacheLock{
private volatile Map map = new HashMap<>();
// 读写锁: 更为粗粒度的操纵
private ReadWriteLock readWriteLock = new
ReentrantReadWriteLock();
// private Lock lock = new ReentrantLock();
// 存,载入的情况下,只期待另外只有一个进程写
public void put(String key,Object value){
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+"载入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()
+"载入OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
// 取,读,任何人都能够读!
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+"载入"+key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()
+"载入OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
/**
* 自定缓存文件
* 不上锁的
*/
class MyCache{
private volatile Map map = new HashMap<>();
// 存,写
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()
+"载入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()
+"载入OK");
}
// 取,读
public void get(String key){
System.out.println(Thread.currentThread().getName()
+"载入"+key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()
+"载入OK");
}
}
实行实际效果如图所示:
阻塞队列:
BlockingQueue 并不是新的物品
什么情况大家会应用 阻塞队列?:线程同步高并发解决,线程池用的较多 !
学好应用序列
加上、清除
四组API
方法 | 抛出异常 | 有传参,不抛出异常 | 堵塞 等候 | 请求超时等候 |
---|---|---|---|---|
加上 | add | offer() | put() | offer(,) |
清除 | remove | poll() | take() | poll(,) |
检验队首原素 | element | peek() | - | - |
编码实例:
package com.kuang.bq;
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws InterruptedException {
test4();
}
/**
* 1. 无传参,抛出异常的方法
*/
public static void test1(){
// 序列的尺寸
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("a"));// true
System.out.println(blockingQueue.add("b"));// true
System.out.println(blockingQueue.add("c"));// true
// System.out.println(blockingQueue.add("d"));
// IllegalStateException: Queue full 抛出异常---序列已满!
System.out.println("===========================");
System.out.println(blockingQueue.element());//
// 查询队首原素到底是谁
System.out.println(blockingQueue.remove());//
System.out.println(blockingQueue.remove());//
System.out.println(blockingQueue.remove());//
// System.out.println(blockingQueue.remove());
// java.util.NoSuchElementException 抛出异常---序列已为空!
}
/**
* 2. 有传参,不抛出异常的方法
*/
public static void test2(){
// 序列的尺寸
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.peek());
// System.out.println(blockingQueue.offer("d"));
// false 不抛出异常!
System.out.println("===========================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
// null 不抛出异常!
}
/**
* 3. 等候,堵塞(一直堵塞)
*/
public static void test3() throws InterruptedException {
// 序列的尺寸
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
// 一直堵塞
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d"); // 序列沒有部位了,一直堵塞等候
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// 沒有这一原素,一直堵塞等候
}
/**
* 4. 等候,堵塞(等候请求超时)
*/
public static void test4() throws InterruptedException {
// 序列的尺寸
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
blockingQueue.offer("a");
blockingQueue.offer("b");
blockingQueue.offer("c");
// blockingQueue.offer("d",2,TimeUnit.SECONDS);
// 等候超出2秒就撤出
System.out.println("===============");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
blockingQueue.poll(2,TimeUnit.SECONDS); // 等候超出2秒就撤出
}
}
SynchronousQueue 同歩序列
沒有容积,进来一个原素,务必等候取下来以后,才可以再往里放一个原素!
put、take
编码举例说明:
package com.haust.bq;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* 同歩序列:
* 和别的的BlockingQueue 不一样, SynchronousQueue 不储存原素
* put了一个原素,务必从里边先take取下来,不然不可以在put进来值!
*/
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue blockingQueue =
new SynchronousQueue<>(); // 同歩序列
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()
+" put 1");
// put进到一个原素
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()
+" put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()
+" put 3");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try {
// 睡眠质量三秒取下一个原素
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"=>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"=>"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"=>"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T2").start();
}
}
实行結果如下图所示:
线程池:3大方式、7大主要参数、4种回绝对策
池化技术性
程序流程的运作,实质:占有系统软件的資源! (提升資源的应用 => 池化技术性)
线程池、数据库连接池、内存池、目标池///… 建立、消毁。十分破坏环境
池化技术性:事前准备好一些資源,有些人得用,就来我这里拿,用完以后还给我。
线程池的益处:
1、减少服务器资源的耗费
2、提升回应的速率
3、便于管理
进程多路复用、能够操纵较大 并发数、管理方法进程
线程池:3大方式
实例编码:
package com.haust.pool;
import java.util.concurrent.ExecutorService;
import java.util.List;
import java.util.concurrent.Executors;
public class Demo01 {
public static void main(String[] args) {
// Executors java工具、3大方式
// Executors.newSingleThreadExecutor();// 建立多带带进程的线程池
// Executors.newFixedThreadPool(5);// 建立一个固定不动尺寸的线程池
// Executors.newCachedThreadPool();// 建立一个可伸缩式的线程池
// 多带带进程的线程池
ExecutorService threadPool =
Executors.newSingleThreadExecutor();
try {
for (int i = 1; i < 100; i++) {
// 应用了线程池以后,应用线程池来建立进程
threadPool.execute(()->{
System.out.println(
Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完,程序流程完毕,关掉线程池
threadPool.shutdown();
}
}
}
7大主要参数
源代码剖析:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService (
new ThreadPoolExecutor(
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(
5,
5,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(
0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue());
}
// 实质ThreadPoolExecutor()
public ThreadPoolExecutor(int corePoolSize, // 关键线程池尺寸
int maximumPoolSize, // 较大 关键线程池尺寸
long keepAliveTime, // 请求超时没人启用便会释放出来
TimeUnit unit, // 请求超时企业
// 阻塞队列
BlockingQueue workQueue,
// 进程加工厂:建立进程的,一般 无需动
ThreadFactory threadFactory,
// 回绝对策
RejectedExecutionHandler handle ) {
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;
}
手动式建立一个线程池
由于具体开发设计中java工具Executors 不安全,因此 必须手动式建立线程池,自定七个主要参数。
实例编码:
package com.haust.pool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
// Executors java工具、3大方式
// Executors.newSingleThreadExecutor();// 建立一个多带带进程的线程池
// Executors.newFixedThreadPool(5);// 建立一个固定不动尺寸的线程池
// Executors.newCachedThreadPool();// 建立一个可伸缩式的线程池
/**
* 四种回绝对策:
*
* new ThreadPoolExecutor.AbortPolicy()
* 金融机构满了,也有人进去
我是这篇文章的创作本人 请您把文章删了 ...
评论于 华为eNSP最稳定的装法