线程池
程序员文章站
2022-05-06 08:00:55
...
- 线程池的思想
- Runnable方式使用线程池
- Callable方式使用线程池
- 死锁
什么是线程池:
存放线程的容器
创建一个线程执行一个任务的缺点:
- 我们创建一个线程执行任务后线程死亡.如果线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
- 比如:中午吃完饭将碗洗干净,晚上接着使用 重复利用,可以节省资源 线程池的好处:
2.Runnable方式使用线程池
创建线程池、Executors类:
- static ExecutorService newFixedThreadPool(int nThreads) 新建固定线程数量的线程池
- int nThreads: 指定线程池中线程的数量
- ExecutorService: 线程池(接口)
Runnable方式使用线程池步骤:
1.创建任务
2.创建线程池
3.往线程池提交任务
// 1.创建任务
public class MyRunnable implements Runnable {
@Override
public void run() { // 新的线程会来执行任务
System.out.println(Thread.currentThread().getName() + "执行啦");
}
}
测试类:
public static void main(String[] args) {
// 2.创建线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
// System.out.println("pool = " + pool);
MyRunnable mr = new MyRunnable();
// 3.往线程池提交任务
pool.submit(mr);
pool.submit(mr);
pool.submit(mr);
pool.submit(mr);
pool.submit(mr);
// 关闭线程池(工作中不需要关闭线程池,7x24)
pool.shutdown();
}
3.Callable方式使用线程池
Callable方式好处:
1.可以抛异常
2.可以有返回值
Callable方式使用线程池步骤?
1.创建一个Callable任务
2.创建线程池
3.提交任务
如何拿到Callable的返回值?
通过Future的get方法
// 1.创建一个Callable任务
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + "执行啦");
return 110;
}
}
测试类:
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 2.创建线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
MyCallable mc = new MyCallable();
// 3.提交任务
pool.submit(mc);
pool.submit(mc);
pool.submit(mc);
pool.submit(mc);
Future<Integer> future = pool.submit(mc);
// 因为不是直接调用call方法,不能直接拿到返回
// 当我们条任务后,线程会来执行call方法,会得到返回值,会将返回值放到Future对象中
// 我们通过Future的get方法得到返回值
System.out.println(future.get());
pool.shutdown();
}
4.死锁
什么是死锁:
多线程竞争共享资源,导致多个线程相互等待,程序无法向下执行
死锁产生的条件:
1.有多个线程
2.有多把锁
3.有同步代码块嵌套
如何避免死锁:
干掉其中某个条件
public class Demo05 {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
new Thread(mr).start();
new Thread(mr).start();
}
}
class MyRunnable implements Runnable {
Object objA = new Object();
Object objB = new Object();
/*
嵌套1 objA
嵌套1 objB
嵌套2 objB
嵌套1 objA
*/
@Override
public void run() {
synchronized (objA) {
System.out.println("嵌套1 objA");
synchronized (objB) {// t2, objA, 拿不到B锁,等待
System.out.println("嵌套1 objB");
}
}
synchronized (objB) {
System.out.println("嵌套2 objB");
synchronized (objA) {// t1 , objB, 拿不到A锁,等待
System.out.println("嵌套2 objA");
}
}
}
}
上一篇: Crazy Search(hash算法)
下一篇: Sunday Search 算法实现