从调用角度来看
从写代码角度看
JUC
wati 和sleep区别
并发和并行?
减少计数CountDownLatch,允许一个或多个线程等待直到在其他线程中执行的一组操作完成的 同步辅助。
方法
- CountDownLatch countDownLatch=new CountDownLatch(7);//构造方法,初始容量为7
- countDownLatch.await();//当前一个或多个线程等待到计数为0
- countDownLatch.countDown();//减少计数
- countDownLatch.getCount();//返回当前计数
例子,有六个同学,当六个同学陆续离开后,班长锁门?
- //案例,等6个同学离开,锁门
- public static void main(String args[]) throws InterruptedException {
- CountDownLatch countDownLatch=new CountDownLatch(6);//初始容量为6
- for(int i=0;i<6;++i)
- {
- new Thread(()->{
- System.out.println("同学"+"离开");
- countDownLatch.countDown();//计数减一
- },"线程"+i).start();
- }
- countDownLatch.await();//等待计数为0
- System.out.println("锁门");
- }
同步辅助类循环栅栏CyclicBarrier,允许一组线程全部等待彼此达到共同屏障点的同步辅助。
方法
例子:集齐7课龙珠就可以召唤神龙?
计数信号量SemaphoreDemo
方法
例子 :6辆车停3个车位
线程池ThreadPool,
线程池概述
优势
主要特点
涉及类的关系,
创建线程的三种方式
- /*
- 创建线程的三种方法
- */
- //第一种 匿名内部类,继承Thread类,重写run()
- Thread th1=new Thread(){
- public void run()
- {
- System.out.println("线程创建的第一种方式!");
- }
-
- };
- //开启线程,
- th1.start();
- //第二种,实现runnable接口
- Thread th2=new Thread(()->{System.out.println("第二种创建线程的方式!");});
- th2.start();
- //第三种 实现callable接口
- FutureTask
task=new FutureTask<>(()->{return 2;}); - Thread th3=new Thread(task);
- th3.start();
- System.out.println(task.get());
线程池(Thread pool)是线程的一种使用模式。线程池维护着多个线程,等待线程监督管理者分配可执行的并发任务。
1.并发,并行,串行的区别
串行:在时间上不能重叠,上一个任务没完成,下一任务必须等待。
并行:在同一时间,同时处理多个任务,在时间上是重叠的,两个任务在同一时刻互不干扰的执行
并发:在一段时间,同时处理多个任务,允许两个任务互相干扰,单核CPU下是不能并行的,可以并发
2.并发的特性
原子性:对于一组操作要么全执行,要么全不执行。保证原子性要用锁synchronized,lock
有序性:程序的执行要按代码的顺序执行,JVM中指令重排,程序执行顺序可能不是代码的顺序导致线程安全问题。解决通过volatile,和锁.
可见性:一个线程修改了共享变量的值,另一个线程可以看到。
3.对线程安全的理解
### Thread类常用方法
* currentThread(),当前正在执行的线程对象的引用
* start(),开始执行线程的方法,启动线程
* yield(),当前线程愿意让出处理器的占用,注意,虽然让出但是可能再次被处理器调用
* sleep():静态方法,让线程睡眠一段时间,睡眠代表的含义是我让出对cpu的使用权,在睡眠的一段时间不会被cpu调用(这样会引发一个问题,有锁怎么办?后面会提到)
* join(),使当前线程等待另一个线程执行完毕后在执行,内部调用的Object的wait()方法实现
*
## 详解Callable,Future与FutureTask
JDK提供了Callable接口与Future类,解决开启一个线程去执行一个任务,这个任务有一个返回值。
### Callable接口
部分源码
```
@FunctionalInterface
public interface Callable
V call() throws Exception;
}
```
简单使用Callable接口的Demo
```
//自定义类实现Callable接口
class Task implements Callable
@Override
public Integer call() throws Exception{
//模拟计算过程,耗费时间1秒,计算结果2
Thread.sleep(1000);
return 2;
}
//测试(也是对Callable的使用)
public static void main(String [] args)
{
ExecutorService executor=Executors.newCachedThreadPool();
Task task=new Task();
Future
//如何得到返回结果
result.get();//结果为2
}
}
```
对上述代码的解释:
* Callable配合线程池工具ExecutorService来使用。
* 然后线程池工具ExecutorService的submit()方法来让Callable执行,返回Future
* 通过Future的get()方法得到结果
### Future接口
部分源码
```
```
简单Demo
```
```
代码详解
### FutureTask
部分源码
```
```
简单Demo
```
```
代码详解
疑问,为什么要有FutureTask?
FutureTask能确保在高并发环境下任务只执行一次。
😄
FutureTask的几个状态
## 线程组和线程优先级