杭州的网站建设,织梦更新网站地图,百度网盘资源搜索引擎,做胎儿羊水鉴定网站阿华代码#xff0c;不是逆风#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力#xff01;#xff01; 希望本文内容能够帮助到你#xff01;#xff01; 目录
引入#xff1a;
一#xff1a;Callable和FutureTask类
1#xff1a;对比Runnable
2#xff1a… 阿华代码不是逆风就是我疯 你们的点赞收藏是我前进最大的动力 希望本文内容能够帮助到你 目录
引入
一Callable和FutureTask类
1对比Runnable
2FutureTask类
3代码示例
示例一Runnable
编辑示例二Callable
二ReentrantLock——可重入锁
1与synchronized的区别
1不会阻塞
2公平锁
3唤醒机制不同
三Semaphore——信号量
1P操作
2V操作
3PV代码示例一
4锁功能
四CountDownLatch
1引入
2代码示例 引入
通过之前的学习我们了解到CAS本质上是JVM替我们封装好的我们没有办法感知到
在java.util.concurrent中存放了一些我们多线程编程时常用的类
看下面的一些接口是不是非常熟悉我们把这个packet包简称为JUC 一Callable和FutureTask类
读法“开了波哦” 译为调用
1对比Runnable
Runnable提供run方法返回值为void——关注过程不关注执行结果
Callable提供call方法返回值类型就是执行结果的类型———更关注结果
2FutureTask类
在Callable中的call方法中完成任务的描述后我们要想办法把这个任务加载给线程Thread
但是Thread类中并没有给出Callable的构造方法于是我们通过FutureTask这个中间类可以理解为加载任务的装置作为媒介发射给Thread 即 Callable中描述方法——卢本伟来啦~~ FutureTask中加载任务——卢本伟已准备就绪~~ Thread中传入futureTask任务执行——卢本伟启动 注 Callable和FutureTask实例化的时候中要写返回结果的类型哦。 futureTask.get()方法是带有阻塞功能的如果线程还没有执行完毕get就会被阻塞等到线程执行完了return的结果就会被get返回回来 3代码示例
老问题计算前5000个数字之和
看以下两段代码——用Callable类写的代码比Runnable类写的代码更加优雅~~
示例一Runnable
package thread;public class ThreadDemon37 {private static int sum 0;//全局变量用来保存最后的结果值public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(new Runnable() {int count 0;//局部变量Overridepublic void run() {for (int i 1 ; i 5000 ; i){count i;}sum count;}});t1.start();t1.join();System.out.println(sum);}}示例二Callable
此处我们不用再引入额外的成员变量了直接借助返回值即可
package thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class ThreadDemon38 {public static void main(String[] args) throws InterruptedException, ExecutionException {CallableInteger callable new CallableInteger() {Overridepublic Integer call() throws Exception {int sum 0;for (int i 0; i 5000; i) {sum i;}return sum;}};//Thread t1 new Thread(callable);//Thread中没有提供构造函数来传入callable//引入FutureTask类未来要完成的任务任务还未执行// 相当于在Callable中确定执行的任务//在FutureTask装置中完成任务加载——卢本伟准备就绪~~~//最后引入线程——卢本伟启动FutureTaskInteger futureTask new FutureTask(callable);Thread t1 new Thread(futureTask);t1.start();t1.join();System.out.println(futureTask.get());//装置获得一下结果}
}补充一点.futureTask.get()方法本身自带阻塞特性如果Callable任务还没有执行完是会一直等待它的返回值结果的
二ReentrantLock——可重入锁
读音“瑞安纯特老科” 翻译为可重入锁
科普ReentrantLock在很早以前是比没有发展起来的synchronized功能更加强大的他提供了两个传统的方法lock和unlock但是在写代码的过程中lock完后往往会忘记unlock解锁所以一般把unlock操作放到finally里面使用
1与synchronized的区别
1不会阻塞
我们知道synchronized加锁如果线程“锁竞争”失败会陷入阻塞等待使用了ReentrantLodk提供了trylock方法后如果加不上锁就会返回false不会阻塞等待。
2公平锁
ReentrantLock中加锁依据是公平锁所有参与“加锁”的线程会被放进队列里面按顺序进行加锁。
3唤醒机制不同
synchronized提供wait和notifyReentrantLock搭配Condition功能比notify强一点
三Semaphore——信号量
读音“赛摸佛尔” 翻译为信号量
科普因为发明信号量的大佬迪杰斯特拉是个荷兰人荷兰语的申请和释放首字母分别是P和V。实际上英语是acquire和release
1P操作
申请一个可用资源可用资源总数就会-1
2V操作
释放一个可用资源可用资源总数就会1
打个比方去停车场停车现在有50个停车位申请一个停车位p操作现有可用停车位为49出来了一辆车v操作现有可用停车位为50
3PV代码示例一
package thread;import java.util.concurrent.Semaphore;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-30* Time: 10:26*/
public class ThreadDemon39 {public static void main(String[] args) throws InterruptedException {Semaphore semaphore new Semaphore(1);//资源数限制为1个semaphore.acquire();System.out.println(p操作);semaphore.acquire();//第二次申请System.out.println(p操作);semaphore.acquire();//第三次申请System.out.println(p操作);}
}4锁功能
信号量是更为广义的锁
代码示例继续沿用解决count计数器线程安全问题的方式
package thread;import java.util.concurrent.Semaphore;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-30* Time: 10:33*/
public class ThreadDemon40 {private static int count 0;//引入Semaphore进行加锁private static Semaphore semaphore new Semaphore(1);public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {try {semaphore.acquire();//加锁for (int i 1 ; i 50000 ; i){count;}} catch (InterruptedException e) {throw new RuntimeException(e);}semaphore.release();//解锁});Thread t2 new Thread(() -{try {semaphore.acquire();//加锁for (int i 1 ; i 50000 ; i){count;}} catch (InterruptedException e) {throw new RuntimeException(e);}semaphore.release();//解锁});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}四CountDownLatch
1引入
latch(锁存器)
举个例子现在下载软件的速度非常快用的是多线程下载方式比如要下载一个1G大小的软件我们把这个任务分成10份分给10个线程同时进行下载最后在拼在一起速度就会快非常多。
这个“拼”的操作就能被CountDownLatch感知到比我们用join要更简单方便一些
2代码示例
package thread;import java.util.Random;
import java.util.concurrent.CountDownLatch;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-30* Time: 10:57*/
public class ThreadDemon41 {public static void main(String[] args) throws InterruptedException {CountDownLatch latch new CountDownLatch(10);//创建10个线程Random random new Random();int time (random.nextInt(4)1)*1000;//time的范围[0,4]-[1,5]-[1000,5000]for(int i 1 ; i 10 ; i){int count i;Thread t new Thread(() -{try {Thread.sleep(random.nextInt(time));//产生的随机数的范围System.out.println(第 count 线程的任务执行完毕);latch.countDown();//告知CountDownLatch有一个任务已经执行完毕了} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}latch.await();//如果CountDownLatch中的任务还没有执行完毕那么CountDownLatch就会陷入阻塞等待System.out.println(所有任务都已经执行完毕了);}
}