多线程学习笔记
一、实现多线程的三种方法
1.继承Thread类
start()开启线程,run()方法顺序执行
一个mian方法下三个thread.start(),不一定顺序执行,cpu安排调度
2.实现runable接口
启动方式不同
多个线程操作一个对象,会造成数据混乱,多个人抢到一张票
如何避免数据混乱得看线程通信
5、synchronized和lock
代码
10、ArrayBlockingQueue
四组API
抛出异常
/**
* add remove element(检测对首元素) 如果超过队列边界(capacity || 0)会抛出异常
* @author luweitong
* @date 2025/2/7 16:53
*/
public class Test1 {
public static void main(String[] args) {
BlockingQueue<String> strings = new ArrayBlockingQueue<>(3);
System.out.println(strings.add("a"));
System.out.println(strings.add("b"));
System.out.println(strings.add("c"));
System.out.println(strings.element());
System.out.println(strings.remove());
System.out.println(strings.remove());
System.out.println(strings.remove());
}
}
不抛出异常
/**
* offer poll peek(取队列队首元素)有返回值,不会抛出异常
* @author luweitong
* @date 2025/2/7 17:00
*/
public class Test2 {
public static void main(String[] args) {
BlockingQueue<String> strings = new ArrayBlockingQueue<String>(3);
System.out.println(strings.offer("a"));
System.out.println(strings.offer("b"));
System.out.println(strings.offer("c"));
System.out.println(strings.offer("d"));
System.out.println(strings.peek());
System.out.println(strings.poll());
System.out.println(strings.poll());
System.out.println(strings.poll());
System.out.println(strings.poll());
}
}
public class Test3 {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<String> strings = new ArrayBlockingQueue<>(3);
strings.put("a");
strings.put("a");
strings.put("a");
//超出容量就阻塞住了 一直等待
// strings.put("a");
System.out.println(strings.take());
System.out.println(strings.take());
System.out.println(strings.take());
//没有元素取,就一直等待
// System.out.println(strings.take());
}
}
synchronousQueue同步队列
/**
* synchronousQueue同步队列
* 和其他的blockQueue不一样,同步队列不存储元素(只存储一个元素)
* put了一个元素必须取出来
* @author luweitong
* @date 2025/2/7 17:11
*/
public class Test4 {
public static void main(String[] args) {
SynchronousQueue<String> queue = new SynchronousQueue<>();
new Thread(() -> {
try {
queue.put("a");
queue.put("b");
queue.put("c");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() +"->"+ queue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() +"->"+ queue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() +"->"+ queue.take());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
11、线程池(重点)
线程池三大方法
/**
* @author luweitong
* @date 2025/2/7 17:22
*/
public class Test1 {
public static void main(String[] args) {
// ExecutorService executorService = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService executorService = Executors.newFixedThreadPool(3);//固定线程
ExecutorService executorService = Executors.newCachedThreadPool();//可伸缩的
try {
for (int i = 0; i < 10; i++) {
executorService.execute(() -> System.out.println(Thread.currentThread().getName() + "ok"));
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
//使用线程池必须shutdown 不然会OOM
executorService.shutdown();
}
}
}
阿里巴巴规范不让使用Executor直接创建,会有OOM风险因为newFixed和newCached
/**
* 自定义线程池,模拟银行业务排队
* @author luweitong
* @date 2025/2/7 17:32
*/
public class Test2 {
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,//核心线程数
5,//最大线程数
1,//存活时间
TimeUnit.SECONDS,//存活时间单位
new ArrayBlockingQueue<Runnable>(3),//阻塞队列
Executors.defaultThreadFactory(),//线程工厂
// new ThreadPoolExecutor.AbortPolicy()//拒绝策略 AbortPolicy默认策略超出线程数再使用就不处理,并抛出异常
// new ThreadPoolExecutor.CallerRunsPolicy()// CallerRunsPolicy 从哪儿来的回哪儿去 输出结果main线程执行了
// new ThreadPoolExecutor.DiscardPolicy()// DiscardPolicy 直接丢弃任务,不会报错
new ThreadPoolExecutor.DiscardOldestPolicy()// DiscardOldestPolicy 会和最早的竞争,不会抛出异常
);
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "执行了");
});
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
threadPool.shutdown();
}
}
}
最大承载 = maximumPoolSize + blockingQueueSize
拒绝策略
应用场景?
12、四大函数式接口
只要是函数式接口都可以用lamda表达式简化
函数式
断言式
消费型接口
供给型接口
13、Stream流式计算
14、forkJoin
工作窃取
forkJoin