做网站要多少钱呀/品牌营销和市场营销的区别
复习概念
Sleep和Wait的区别
- Sleep是Thread的静态方法,wait是Object的方法,任何对象实例都可以使用
- sleep不会释放锁,他也不需要占用锁,暂停。wait会释放锁,但是调用他的前提是线程占有锁
- 他们都可以被Interrupted方法中断。在哪里停,在哪里起
并发并行
并发:同一时刻,多个线程访问同一资源
并行:多项工作一起执行,之后汇总
线程的状态
Thread.status
管程
monitor监视器 所说的锁
是一种同步机制,保证同一时间,只有一个线程 访问被保护的数据或者代码
用户线程和守护线程
用户线程:自定义线程,平时用到的具体逻辑
守护线程:垃圾回收线程
主线程已经结束了,用户线程还在运行,jvm存活、
如果程序中没有用户线程了,守护线程也会结束,在执行start之前设置是否是守护线程。
卖票程序:
package com.policy.thread;class Ticket{private int ticket =30;public synchronized void sale(){if(ticket>0){System.out.println(Thread.currentThread().getName()+"卖出:"+(ticket--)+"剩余:"+ticket);}}
}public class SaleTicket {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"a").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"b").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 40; i++) {ticket.sale();}}},"c").start();}}
可重入锁
Lock.lock()
Lock.unlock()
lock不是java内置的,synchronized是java关键字
sync不需要手动释放锁,lock上锁之后需要手动释放锁
package com.policy.thread;import java.util.concurrent.locks.ReentrantLock;class LTicket{private int num=30;//创建可重入锁private final ReentrantLock lock = new ReentrantLock();//卖票方法public void sale(){//上锁lock.lock();try {if(num>0){System.out.println(Thread.currentThread().getName()+"卖出"+(num--)+"剩余"+num);}} catch (Exception e) {throw new RuntimeException(e);} finally {//解锁lock.unlock();}}
}public class LTicketSale {public static void main(String[] args) {LTicket lTicket = new LTicket();//创建线程 表达式new Thread(()->{for (int i = 0; i < 40; i++) {lTicket.sale();}},"a").start();new Thread(()->{for (int i = 0; i < 40; i++) {lTicket.sale();}},"b").start();new Thread(()->{for (int i = 0; i < 40; i++) {lTicket.sale();}},"c").start();}}
Lock 与Sync总结
1、Lock是一个接口,sync是java的关键字,是一种内置的实现语言
2、当sync发生异常时,会自动释放占有的锁,因此不会导致死锁的发生;
Lock在发生异常时,如果没有主动通过unLock释放锁,则很可能会造成死锁现象,因此在Finally中释放锁是很必要的。
3、Lock会让等待锁的线程响应中断,而sync却不会中断等待线程,使用sync会一直等待下去,不能够响应中断。
4、通过lock可以知道有没有成功获取锁,而Sync却无法办到。
5、Lock可以提高多个线程读操作的效率。
线程通信
第一步:创建资源类,在资源类中创建属性和方法
第二步:方法中
判断、干活、通知
第三步:创建多个线程,调用资源类的操作方法
第四步:防止虚假唤醒问题
package com.policy.thread.Thread202308;
class Share{//线程等待和唤醒private int num=0;public synchronized void incr() throws InterruptedException {//加一操作if(num!=0){//不等于0说明不需要加一 等待this.wait();}//加一num++;System.out.println(Thread.currentThread().getName()+"::"+num);//唤醒其他线程 可以减一了this.notifyAll();}public synchronized void decr() throws InterruptedException {if(num!=1){//等待this.wait();}//减一num--;System.out.println(Thread.currentThread().getName()+"::"+num);this.notifyAll();}
}public class ThreadDemo01 {public static void main(String[] args) {Share share=new Share();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.incr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"aa").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.decr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"bb").start();}}
此方法 如果多了线程之后 增加CCDD线程执行操作会有虚假唤醒的问题,问题的原因是出现在判断条件中
A释放之后 BCD都有机会抢到,C抢到了C也会等待,然后再去让其他线程抢,继续唤醒A线程,WAIT有一个问题,就是在哪等待,唤醒之后在哪执行,那么会执行if下面的语句,第二次执行A可能会继续执行+1
解决:把判断放到while循环中,无论什么时候唤醒,都会在执行循环的判断条件。
package com.policy.thread.Thread202308;
class Share{//线程等待和唤醒private int num=0;public synchronized void incr() throws InterruptedException {//加一操作while(num!=0){//不等于0说明不需要加一 等待this.wait();}//加一num++;System.out.println(Thread.currentThread().getName()+"::"+num);//唤醒其他线程 可以减一了this.notifyAll();}public synchronized void decr() throws InterruptedException {while(num!=1){//等待this.wait();}//减一num--;System.out.println(Thread.currentThread().getName()+"::"+num);this.notifyAll();}
}public class ThreadDemo01 {public static void main(String[] args) {Share share=new Share();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.incr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"aa").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.decr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"bb").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.incr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"cc").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {share.decr();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"dd").start();}}
Lock实现上锁和线程通信
lock.lock();上锁
lock.unlock();解锁
condition.await();等待
condition.signalAll();唤醒其他线程
package com.policy.thread.Thread202308;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class Share02{//创建锁private Lock =new ReentrantLock();Condition condition = lock.newCondition();private int num = 0;public void incr() throws InterruptedException {//上锁lock.lock();try {while (num!=0){//通信等待condition.await();}//干活num++;System.out.println(Thread.currentThread().getName()+"::"+num);condition.signalAll();} finally {//解锁lock.unlock();}//判断 干活 通信}public void decr() throws InterruptedException {//上锁lock.lock();try {while (num!=1){//通信等待condition.await();}//干活num--;System.out.println(Thread.currentThread().getName()+"::"+num);condition.signalAll();} finally {lock.unlock();}//判断 干活 通信}
}public class ThradDemo02 {public static void main(String[] args) {Share02 share02 = new Share02();new Thread(()->{try {for (int i = 0; i < 10; i++) {share02.incr();}} catch (InterruptedException e) {throw new RuntimeException(e);}},"A").start();new Thread(()->{try {share02.decr();} catch (InterruptedException e) {throw new RuntimeException(e);}},"B").start();new Thread(()->{try {for (int i = 0; i < 10; i++) {share02.decr();}} catch (InterruptedException e) {throw new RuntimeException(e);}},"C").start();new Thread(()->{try {for (int i = 0; i < 10; i++) {share02.decr();}} catch (InterruptedException e) {throw new RuntimeException(e);}},"D").start();}
}
线程定制化通信
以上不管使用那种方式上锁或者进行通信 但是都不能将数据进行有顺序的固定化的通信
例如 指定三个线程,按照要求执行
AA打印5次 BB打印10次 CC打印15次
进行十轮
package com.policy.thread.Thread202308;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class ShareResource{private int falg =1;//1表示A的 2-B 3C//创建锁private Lock lock =new ReentrantLock();//创建三个conditionprivate Condition c1= lock.newCondition();private Condition c2 = lock.newCondition();private Condition c3=lock.newCondition();public void print5(int loop) throws InterruptedException {lock.lock();try {while (falg!=1){//等待 不打印Ac1.await();}for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+"::"+i+"当前是第轮:"+loop);}//通知falg=2;//修改flag标示位的值c2.signal();//此时在A线程中 唤醒的是C2} finally {lock.unlock();}}public void print10(int loop) throws InterruptedException {lock.lock();//上锁try {//等待while (falg!=2){c2.await();}//干活for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+"::"+i+"当前是第轮:"+loop);}//通知falg=3;c3.signal();} finally {lock.unlock();}}public void print15(int loop) throws InterruptedException {lock.lock();//上锁try {//等待while (falg!=3){c3.await();}//干活for (int i = 0; i < 15; i++) {System.out.println(Thread.currentThread().getName()+"::"+i+"当前是第轮:"+loop);}//通知falg=1;c1.signal();} finally {lock.unlock();}}
}public class ThreadDemo3 {public static void main(String[] args) {ShareResource shareResource = new ShareResource();new Thread(()->{for (int i = 0; i < 10; i++) {try {shareResource.print5(i);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"A").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {shareResource.print10(i);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"B").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {shareResource.print15(i);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"C").start();}
}
集合的线程安全
集合不安全的情况
List线程不安全的例子
在一边向list中add 一边需要输出list时 有可能会报错:并发修改异常
Exception in thread "2" Exception in thread "5" Exception in thread "1" Exception in thread "4" java.util.ConcurrentModificationException
package com.policy.thread.Thread202308;import java.util.ArrayList;
import java.util.List;
import java.util.UUID;public class ThreadDemo04 {public static void main(String[] args) {List<String> list = new ArrayList<>();for (int i = 0; i < 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);},String.valueOf(i)).start();}}
}
解决方案:
list之所以会报错并发修改异常 原因是list并没有加上synchronized关键字修饰
1、Vcetor 少用
Vector 的方法上 都加上了synchronized
package com.policy.thread.Thread202308;import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.Vector;public class ThreadDemo04 {public static void main(String[] args) {List<String> list = new Vector<>();for (int i = 0; i < 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list);},String.valueOf(i)).start();}}
}
2、Collections
List<String> list = Collections.synchronizedList(new ArrayList<>());
通过调用Collections中的synchronized方法 即可将new出的List变成线程安全的
一般也少用
3、CopyOnWriteArrayList
List<String> list =new CopyOnWriteArrayList<>();
写时复制技术
可以并发的读取list的内容,但是需要向list写入的时候,需要复制一份写入新内容,然后将两份合并起来,读取合并后的新内容。兼顾了并发读 和写的操作
HashSet不安全的情况
Set<String> set =new HashSet<>();
for (int i = 0; i < 30; i++) {new Thread(()->{set.add(UUID.randomUUID().toString().substring(0,8));System.out.println(set);},String.valueOf(i)).start();
}
Exception in thread "5" Exception in thread "17" Exception in thread "21" Exception in thread "23" Exception in thread "24" Exception in thread "28" java.util.ConcurrentModificationException
解决方法
CopyOnWriteArraySet
Set<String> set = new CopyOnWriteArraySet<>();
HashMap不安全的情况
Map<String,String> map =new HashMap<>();
for (int i = 0; i < 30; i++) {new Thread(()->{map.put(UUID.randomUUID().toString().substring(0,8),"1111");System.out.println(map);},String.valueOf(i)).start();
}
解决方案
Map<String,String > map =new ConcurrentHashMap<>();
多线程锁
synchronized实现同步方法的基础:java每个对象都可以作为锁,具体的表现有三种形式。
对于普通的同步方法,锁的是当前实例的对象
对于静态同步方法,锁的是当前类的Class
对于同步方法块,锁的是Synchronized括号里面的配置对象
公平锁和非公平锁
非公平锁:线程会饿死,但是执行效率高
公平锁:阳光普照,效率相对低
可重入锁
synchronized 和Lock都是可重入锁
syn是一种隐式的可重入锁,Lock是显示的可重入锁 可重入锁也叫递归锁
死锁
两个或者两个以上的进程在执行过程中,因为争夺资源而造成的一种互相等待的现象,如果没有外力干涉他们就无法执行下去的现象、
产生死锁的原因:
1、系统资源不足
2、进程运行的推进顺序不合适
3、资源分配不当
package com.policy.thread.Thread202308;import java.sql.Time;
import java.util.concurrent.TimeUnit;public class DeadLock {//创建两个对象static Object a = new Object();static Object b = new Object();public static void main(String[] args) {new Thread(()->{synchronized (a){System.out.println(Thread.currentThread().getName()+"持有A,试图获取B");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (b){System.out.println(Thread.currentThread().getName()+"获取B");}}},"A").start();new Thread(()->{synchronized (b){System.out.println(Thread.currentThread().getName()+"持有B,试图获取A");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (a){System.out.println(Thread.currentThread().getName()+"获取A");}}},"B").start();}
}
验证死锁:
1、jps 类似于:linux ps -ef
2、jstack :jvm自带的堆栈跟踪工具
Callable接口
Callable接口可以提供返回值
Runnable和Callable 区别
run call
无返回值 有返回值
无异常抛出 有异常抛出
package com.policy.thread.Thread202308.callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;//实现runnable接口
class Mythread1 implements Runnable{@Overridepublic void run() {}
}class Mythread2 implements Callable{@Overridepublic Object call() throws Exception {return 200;}
}public class Demo1 {public static void main(String[] args) throws ExecutionException, InterruptedException {//调用runnable接口Mythread1 mythread1 = new Mythread1();Thread thread = new Thread(mythread1);thread.setName("a");thread.start();//调用callable//FutureTask是runnable的实现接口//future 构造方法可以传递CallableFutureTask<Integer> futureTask = new FutureTask<>(new Mythread2());//以上的代码 可以用lambda表达式做简化FutureTask<Integer> futureTask1 = new FutureTask<>(()->{return 1024;});//FutureTask 原理 为什么叫未来任务new Thread(futureTask1).start();System.out.println(futureTask1.get());}}
Future优缺点
优点:future结合线程池异步多任务配合,能显著的提高程序的执行效率。
package com.policy.thread.JUC;import java.util.concurrent.*;public class FutureThreadPoolDemo {public static void main(String[] args) throws InterruptedException, ExecutionException {long start = System.currentTimeMillis();//线程池ExecutorService threadPool = Executors.newFixedThreadPool(3);//开启多个异步任务 处理FutureTask<String> task1 = new FutureTask<>(() -> {TimeUnit.MILLISECONDS.sleep(500);return "task1 over";});FutureTask<String> task2 = new FutureTask<>(() -> {TimeUnit.MILLISECONDS.sleep(300);return "task2 over";});FutureTask<String> task3 = new FutureTask<>(() -> {TimeUnit.MILLISECONDS.sleep(300);return "task3 over";});threadPool.submit(task1);threadPool.submit(task2);threadPool.submit(task3);//获取结果System.out.println(task1.get());System.out.println(task2.get());System.out.println(task3.get());threadPool.shutdown();long end = System.currentTimeMillis();System.out.println(end-start+"毫秒");System.out.println(Thread.currentThread().getName()+"执行结束");}private static void m1() throws InterruptedException {long start = System.currentTimeMillis();TimeUnit.MILLISECONDS.sleep(500);TimeUnit.MILLISECONDS.sleep(300);TimeUnit.MILLISECONDS.sleep(300);long end = System.currentTimeMillis();System.out.println(end-start+"毫秒");System.out.println(Thread.currentThread().getName()+"执行结束");}
}
缺点 FutureTask的缺点、
get方法会阻塞:
package com.policy.thread.JUC;import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;public class FutureAPIDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<String> stringFutureTask = new FutureTask<>(() -> {System.out.println(Thread.currentThread().getName() + "come in!");TimeUnit.SECONDS.sleep(5);return "task over";});Thread thread = new Thread(stringFutureTask);thread.start();System.out.println(stringFutureTask.get());//非要等到结果 才会执行//由于会在上面get不到结果 需要等五秒之后才能get到 所以 线程会阻塞五秒 才能执行下面的输出System.out.println("main over");}
}
1、get容易阻塞,一般放到最后才执行
2、如果不愿放到最后,我希望过时不候,可以自动离开
System.out.println(stringFutureTask.get(3,TimeUnit.SECONDS));
最后超过时间会抛出异常
JUC的辅助类
1、减少计数的CountDownLatch
CountDownLatch主要有两个方法,当一个或者多个线程调用 await方法时,这个线程会阻塞。
调用CountDown方法会将计数器减一。当计数器变为0时,因await方法阻塞的线程会被唤醒,继续执行。
2、循环栅栏CyclicBarrier
3、信号灯Semaphore
读写锁
悲观锁
不支持并发操作
乐观锁
表锁
操作表中的一行的记录或者数据 整张表都上锁
行锁
操作表中第一行的数据,只对第一行上锁,其他线程可以操作其他行的数据
读锁
共享锁
写锁
独占锁
读写锁都有可能发生死锁的状况
读锁发生死锁的状况
读写锁的例子,如果不加上读写锁,那么在还没有写完时就会执行读取的操作,
加锁之后,写完才可以读,并且可以看到结果中写操作是独占的,读操作是共享的。
读写锁:一个资源可以被多个读操作线程访问,一个资源只能被一个写操作线程访问,一个资源不能同时存在读写线程访问,读写互斥,写写互斥,读读共享。
无锁时,多个线程共 全的情况发生。
添加锁synchronized或者Lock这样就变成了线程独占的了,资源不共享,变成单线程的了
添加读写锁ReentrantReadWriteLock:相较与上面的锁,读读操作变成了共享的了,提升性能,多线程可共同操作(读)一个资源
缺点:造成 锁饥饿,一直读没有写操作、 读的时候不能写,读完了才可以写,写的时候可以读。=会造成锁降级的过程
锁降级
写入锁降级为读锁的过程
jdk8 中锁降级的过程:
阻塞队列
BlockingQueue阻塞队列
当队列为空的时候,从对列中获取元素,只能阻塞
当队列是满的时候,向队列中添加元素,阻塞
好处是,一系列的判断是否为空,满的操作,都是自动完成的。我们不需要关心什么时候需要挂起线程,什么时候需要唤醒线程。
这些都是阻塞队列封装好的。
阻塞队列的架构
ArrayBlockingQueue:基于数组实现的阻塞队列,内部维护了一个定长的数组,以便缓存队列的数据对象。
LinkedBlockingQueue:由链表组成的阻塞队列
DelayQueue:使用优先级队列 实现的延迟无界的队列。
PriorityBlockQueue:支持优先级排序的队列
SynchronousQueue:无缓冲的阻塞队列,不存储元素的的阻塞队列,只存单个元素‘
LinkedTransferQueue:链表组成的无界阻塞队列
LinkedBlockDeque:有链表组成的双向阻塞队列
add、remove这一组的话,在长度范围内正常操作,add会返回true或者false 超过之后会抛出异常
offer和poll offer满了之后添加不会抛异常,会返回false 队列空了之后,执行poll,会进行返回null 不会抛异常
put 当队列满了之后会一直阻塞在那里,take也是,队列空了之后不会结束也不会完成 会停留在那里
第四组的offer poll设置超时时间,在时间范围内阻塞 超时就会退出 offer会返回false
ThreadPool线程池
一种线程使用模式,线程过多会带来调度的开销,进而影响缓存局部的和整体的性能。线程池维护多个线程,等待着监督管理者分配可并发执行的任务。
优点:降低资源消耗,提高响应速度。提搞可管理性
线程池的分类:
Executors.newFixedThreadPool(int)一个线程池,里面多个线程
Executors.newSingleThreadExecutor()一个线程池一个线程
Executors.newCachedThreadPool()缓存线程池,理论上可无限扩容
举例
newFixedThreadPool
package com.policy.thread.Thread202308.pool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo1 {public static void main(String[] args) {//fixedExecutorService threadpool1 = null;//5个窗口try {threadpool1 = Executors.newFixedThreadPool(5);for (int i = 0; i < 10; i++) {//执行threadpool1.execute(()->{System.out.println(Thread.currentThread().getName()+"办理业务");});}} catch (Exception e) {throw new RuntimeException(e);} finally {threadpool1.shutdown();}}
}
newSingleExecutor()
package com.policy.thread.Thread202308.pool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo1 {public static void main(String[] args) {//fixedExecutorService threadpool1 = Executors.newFixedThreadPool(5);//5个窗口ExecutorService threadpool2 = Executors.newSingleThreadExecutor();//一个线程try {for (int i = 0; i < 10; i++) {//执行threadpool2.execute(()->{System.out.println(Thread.currentThread().getName()+"办理业务");});}} catch (Exception e) {throw new RuntimeException(e);} finally {threadpool2.shutdown();}}
}
相当于开启了一个线程 只输出一个线程名
newCacheThreadPool()
package com.policy.thread.Thread202308.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo1 {
public static void main(String[] args) {
//fixed
ExecutorService threadpool1 = Executors.newFixedThreadPool(5);//5个窗口
ExecutorService threadpool2 = Executors.newSingleThreadExecutor();//一个线程
ExecutorService threadpool3 = Executors.newCachedThreadPool();
try {
for (int i = 0; i < 10; i++) {
//执行
threadpool3.execute(()->{
System.out.println(Thread.currentThread().getName()+"办理业务");
});
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
threadpool3.shutdown();
}
}
}
执行结果:
可以看到此处执行最多创建了7个线程,来执行一个循环任务,相当于开了七个窗口,理论上可扩充更灵活
底层实现
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
三个线程池的底层都是new ThreadPoolExecutor
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.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}
7个线程池参数:
int corePoolSize:常驻的核心线程的数量
int maximumPoolSize :最大的线程数量
long keepAliveTime, TimeUnit unit,存活时间 及存活时间的单位,非核心线程的空闲的存活时间,超出时间就会关闭掉
BlockingQueue<Runnable> workQueue,常驻的线程数量用完之后,进入阻塞队列
ThreadFactory threadFactory,线程工厂,用于创建线程
RejectedExecutionHandler handler拒绝策略
线程池的工作流程以及7个参数的使用
大致的流程图
执行了线程池的execute之后,线程池才会创建,
以上的图中核心线程数2 最大线程数5 阻塞队列数3
当有一个线程进到线程池之后,会最先进入核心线程中执行,如果核心线程此时已满,会加到阻塞队列中,如果阻塞队列长度也满了,那么会创建核心线程池之外的线程进行执行。如果最大线程池也满了,会根据线程策略进行操作
拒绝策略jdk内置的拒绝策略
AbortPolicy(默认) :直接抛出RejectedExecutionException异常,阻止系统正常运行。
CallerRunsPolicy:调用者运行,一种调节机制,该策略不会抛弃任务,也不会抛出异常,而是将任务回退给调用者,降低任务流量
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入到队列中尝试再次提交当前任务
DiscardPolicy:该策略默默的丢弃无法处理的任务,不予以任何处理也不抛出异常。如果允许丢失任务,这是最好的策略
自定义线程池
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor传参数的方式进行创建
原因1允许阻塞队列的请求长度是Integer.MAX_VALUE,可能会造成大量的线程堆积。导致OOM
实际中自己自定义线程池进行操作
Fork/join分支合并框架
可以将一个大任务,拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果进行输出。
FORK:把一个任务进行拆分,大事化小
Join:把拆分任务结果进行合并
相关文章:

JUC内容概述
复习概念 Sleep和Wait的区别 Sleep是Thread的静态方法,wait是Object的方法,任何对象实例都可以使用sleep不会释放锁,他也不需要占用锁,暂停。wait会释放锁,但是调用他的前提是线程占有锁他们都可以被Interrupted方法…...

postcss安装和使用
要安装和使用 PostCSS,你可以按照以下步骤操作: 步骤一:安装 PostCSS 在项目目录下,通过 npm 初始化一个新的 package.json 文件(如果还没有): npm init -y 安装 PostCSS 和必要的插件&#x…...

macOS 13 Ventura (苹果最新系统) v13.6.6正式版
macOS 13 Ventura是苹果电脑的全新操作系统,它为用户带来了众多引人注目的新功能和改进。该系统加强了FaceTime和视频通话的体验,同时优化了邮件、Safari浏览器和日历等内置应用程序,使其更加流畅、快速和安全。特别值得一提的是,…...

WordPress Git主题 响应式CMS主题模板
分享的是新版本,旧版本少了很多功能,尤其在新版支持自动更新后,该主题可以用来搭建个人博客,素材下载网站,图片站等 主题特点 兼容 IE9、谷歌 Chrome 、火狐 Firefox 等主流浏览器 扁平化的设计加响应式布局&#x…...

安卓国内ip代理app,畅游网络
随着移动互联网的普及和快速发展,安卓手机已经成为我们日常生活和工作中不可或缺的一部分。然而,由于地理位置、网络限制或其他因素,我们有时需要改变或隐藏自己的IP地址。这时,安卓国内IP代理App便成为了一个重要的工具。虎观代理…...

Day53:WEB攻防-XSS跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本
目录 MXSS UXSS:Universal Cross-Site Scripting HTML&SVG&PDF&SWF-XSS&上传&反编译(有几率碰到) SVG-XSS PDF-XSS Python生成XSS Flash-XSS 知识点: 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-…...

k8s安装traefik作为ingress
一、先来介绍下Ingress Ingress 这个东西是 1.2 后才出现的,通过 Ingress 用户可以实现使用 nginx 等开源的反向代理负载均衡器实现对外暴露服务,以下详细说一下 Ingress,毕竟 traefik 用的就是 Ingress 使用 Ingress 时一般会有三个组件: …...

如何在Windows 10中打开屏幕键盘?这里有详细步骤
本文解释了在Windows 10中打开或关闭屏幕键盘的不同方法,还解释了如何将屏幕键盘固定到开始菜单。 使用屏幕键盘的快捷键 如果你喜欢快捷方式,你会喜欢这个:按物理键盘上的WinCTRLO。这将立即显示屏幕键盘,而无需通过轻松使用。…...

【Pt】马灯贴图绘制过程 03-制作油渍、积尘效果
目录 效果 一、制作油渍效果 1.1 基本油渍 1.2 流淌的油渍痕迹 二、制作浮尘效果 三、制作积尘效果 效果 一、制作油渍效果 1.1 基本油渍 将上篇制作的“锈迹_深色”和“锈迹_浅色”两个文件夹再次合并为一个文件夹 这里就命名为“锈迹” 添加一个填充图层 设置Base …...

python-numpy-常用函数详解
文章目录 一、函数详解np.empty(num_points)np.zeros(shape, dtypefloat, orderC)np.tile(A, reps)np.newaxisnumpy.stack(arrays, axis0)np.roll(a, shift, axisNone) 二、实例矩阵进行扩展三行,使得每一行都与第一行相同二维数组每行减去不同的数 一、函数详解 n…...

UE小:基于UE5的两种Billboard material(始终朝向相机材质)
本文档展示了两种不同的效果,分别是物体完全朝向相机和物体仅Z轴朝向相机。通过下面的演示和相关代码,您可以更加直观地理解这两种效果的差异和应用场景。 1. 完全朝向相机效果 此效果下,物体将完全面向相机,不论相机在哪个角度…...

spring boot actuator 安全配置 springboot的安全性
关于springboot Actuator框架的安全配置方案: 加入security安全验证框架 方案一: 配置信息: spring:security:user:password: adminname: adminmanagement:endpoints:web:base-path: /monitorexposure:include: "*"# 排除端点e…...

macOS Sonoma如何查看隐藏文件
在使用Git进行项目版本控制时,我们可能会遇到一些隐藏文件,比如.gitkeep文件。它通常出现在Git项目的子目录中,主要作用是确保空目录也可以被跟踪。 终端命令 在尝试查看.gitkeep文件时,使用Terminal命令来显示隐藏文件 default…...

深入浅出:语言模型的原理、实战与评估
深入浅出:语言模型的原理、实战与评估 1. 引言1.1. 关于语言模型1.2. 语言模型的重要性 2. 语言模型简介2.1. 语言模型的类型2.2. 技术演进 3. 语言模型的原理3.1. 概率基础3.2. 深度学习模型 4. 语言模型的实战应用4.1. 数据准备4.2. 模型训练4.3. 应用场景 5. 语言…...

基于ssm的线上旅行信息管理系统论文
摘 要 随着旅游业的迅速发展,传统的旅行信息查询管理方式,已经无法满足用户需求,因此,结合计算机技术的优势和普及,特开发了本线上旅行信息管理系统。 本论文首先对线上旅行信息管理系统进行需求分析,从系…...

Jupyter开启远程服务器(最新版)
Jupyter Notebook 在本地进行访问时比较简单,直接在cmd命令行下输入 jupyter notebook 即可,然而notebook的作用不止于此,还可以用于远程连接服务器,这样如果你有一台服务器内存很大,但是呢你又不喜欢在linux上进行操作…...

【SpringCloud微服务实战10】DevOps自动化部署微服务项目(Jenkins+Docker+K8s)
一、什么是 DevOps DevOps 是一种重视软件开发人员(Developer)和运维人员(Operations)之间沟通与协作的文化、运动或实践,目标在于快速交付高质量的软件产品和服务。DevOps 强调自动化流程、持续集成与交付(CI/CD)、以及通过工具链、敏捷方法论和跨职能团队协作来增强软…...

DSVPN实验报告
一、分析要求 1. 配置R5为ISP,只能进行IP地址配置,所有地址均配为公有IP地址。 - 在R5上,将接口配置为公有IP地址,并确保只进行了IP地址配置。 2. R1和R5之间使用PPP的PAP认证,R5为主认证方;R2于R5之间…...

Linux:Jenkins:参数化版本回滚(6)
上几章我讲到了自动集成和部署 Linux:Jenkins全自动持续集成持续部署(4)-CSDN博客https://blog.csdn.net/w14768855/article/details/136977106 当我们觉得这个页面不行的时候,需要进行版本回滚,回滚方法我这里准备了…...

Haproxy2.8.1+Lua5.1.4部署,haproxy.cfg配置文件详解和演示
目录 一.快速安装lua和haproxy 二.配置haproxy的配置文件 三.配置haproxy的全局日志 四.测试负载均衡、监控和日志效果 五.server常用可选项 1.check 2.weight 3.backup 4.disabled 5.redirect prefix和redir 6.maxconn 六.调度算法 1.静态 2.动态 一.快速安装lu…...

GenICam-GenApi简介
EMVA 1288标准之GemICam-GenApi学习与解读 背景介绍 当前相机不仅用于传输图像,还打包了越来越多的功能。这就导致相机的编程接口越来越复杂。 GenICam的目标是为所有类型的相机提供一个通用的编程接口,无论相机使用何种接口技术,或者实现…...

如何创建纯净版Django项目并启动?——让Django更加简洁
目录 1. Django的基本目录结构 2. 创建APP 2.1 创建app 2.2 配置文件介绍 3. 迁移数据库文件 3.2 连接数据库 3.1 创建迁移文件 3.2 同步数据库 4. 纯净版Django创建 4.1 剔除APP 4.2 剔除中间件 4.3 剔除模板引擎 5. 最终 1. Django的基本目录结构 在我们创建Django项…...

蓝桥杯 2022 省A 选数异或
一种比较无脑暴力点的方法,时间复杂度是(nm)。 (注意的优先级比^高,记得加括号(a[i]^a[j])x) #include <iostream> #include <vector> #include <bits/stdc.h> // 包含一些 C 标准库中未包含的特定实现的函数的头文件 usi…...

计数器选型参数,结构原理,工艺与注意问题总结
🏡《总目录》 目录 1,概述2,工作原理2.1,触发器(Flip-Flop):2.2,计数器结构:2.3,计数操作:2.4,模式控制:2.5,扩展与级联:3,结构特点3.1,触发器3.2,加法器3.3,时钟控制电路...

Android 性能优化实例分享-内存优化 兼顾效率与性能
背景 项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率,做了内存优化和下载导出优化,具体效果如最后的一节的表格所示。 下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍: 一.拍摄前预览页面优化 预览效果问题 存在…...

IT服务监督管理案例分析题
习题一 根据国家电网提出建设智能电网,信息化作为推进电力企业实现发展战略目标的和目标的核心保障体系,作用日益突出。这其中更需要进步推动信息运维综合监管系统的深化应用工作。 某软件股份有限公司是国内IT运维管理服务提供商,为多家电…...

【spring】AbstractApplicationContext 的refresh() 方法学习
上一篇我们一起学习了【spring】FileSystemXmlApplicationContext 类学习 AbstractApplicationContext 的refresh() 方法介绍 AbstractApplicationContext的refresh()方法仍然是整个Spring应用程序上下文初始化的核心流程入口。大体上的刷新生命周期依然保持一致。 refresh(…...

零基础10 天入门 Web3之第1天
10 天入门 Web3 Web3 是互联网的下一代,它将使人们拥有自己的数据并控制自己的在线体验。Web3 基于区块链技术,该技术为安全、透明和可信的交易提供支持。我准备做一个 10 天的学习计划,可帮助大家入门 Web3: 想要一起探讨学习的…...

【1】网络协议基础概念
【1】网络协议基础知识 1、互联网2、为什么要学习网络协议3、学习中需要搭建的环境4、客户端-服务器5、Java 的跨平台原理6、C/C的跨平台原理7、一个简单的SpringBoot项目(1) pom.xml(2) application.yml(3) NetworkStudyApp.java(4) SwaggerConfig.java(5) HelloWorldControll…...

flutter 中 GetxController 和 GetxService 的区别和使用场景
区别: GetxController: GetxController 用于管理特定页面或 widget 的状态。每个页面或 widget 可以拥有一个或多个 GetxController,用于管理其自身的状态和逻辑。GetxController 是短暂存在的,通常与页面或 widget 的生命周期相关…...