线程池&死锁&线程状态&定时器
能够描述Java中线程池运行原理
使用一个容器(集合)存储一些线程
当我们要使用线程的时候,从容器中取出
使用完毕线程,把线程在归还给线程池
可以重复使用线程,可以提高程序的效率,避免了频繁的创建线程和销毁线程
能够描述死锁产生的原因
出了两个同步代码块的嵌套
线程一拿着线程二的锁
线程二拿着线程一的锁
两个线程都处于阻塞状态,都不会继续执行
能够说出线程6个状态的名称
新建,运行,阻塞,睡眠(计算等待),无限等待,死亡(退出)
能够理解等待唤醒案例
两个线程之间的协作
包子铺线程做好包子-->唤醒吃货线程-->包子铺线程等待-->吃货线程吃包子-->吃完包子-->唤醒包子铺线程-->吃货线程等待
能够使用定时器
void schedule(TimerTask task, long delay) 在指定的毫秒值之后,只执行一次定时任务
void schedule(TimerTask task, long delay, long period) 在指定的毫秒值之后,每隔多少毫秒反复执行定时任务
void schedule(TimerTask task, Date time) 在指定的时间和日期之后,只执行一次定时任务
void schedule(TimerTask task, Date firstTime, long period) 在指定的时间和日期之后,每隔多少毫秒反复执行定时任务
第一章 线程池
1.线程池的思想
2.线程池概述
/*
java.util.concurrent.Executors:是一个创建线程池的工具类,专门用来生产线程池,里边的方法都是静态的
静态方法:
static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
参数:
int nThreads:创建的线程池,包含的线程数量 100 包含100个线程 1000包含1000个线程
返回值:
ExecutorService:就是一个线程池,ExecutorService是一个接口,返回的是ExecutorService接口的实现类对象
java.util.concurrent.ExecutorService:描述线程池的接口
Future<?> submit(Runnable task) 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
<T> Future<T> submit(Callable<T> task) 提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
参数:
Runnable task:传递Runnable接口的实现类对象(线程任务)==>重写run方法,设置线程任务==>run方法没有返回值
Callable<T> task:传递Callable接口的实现类对象(线程任务)==>重写call方法,设置线程任务==>call方法有返回值
返回值:
Future:用来接收线程任务的返回值==>用来接收call方法的返回值
*/
3.使用线程池执行Runnable接口的线程任务(重点)
package com.itheima.demo01ThreadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
使用线程池执行Runnable接口的线程任务(重点)
使用步骤:
1.使用线程池工厂类Executors中的静态方法newFixedThreadPool,创建一个包含指定线程数量的线程池
2.创建一个Runnable接口的实现类,重写run方法,设置线程任务(匿名内部类简化)
3.使用线程池ExecutorService中的方法submit,获取线程执行线程任务
注意:submit方法会[自动]从线程池中取出一个线程,执行线程任务,执行完毕任务,会[自动]的把线程在归还给线程
*/
public class Demo01ThreadPool {
public static void main(String[] args) {
//1.使用线程池工厂类Executors中的静态方法newFixedThreadPool,创建一个包含指定线程数量的线程池
ExecutorService es = Executors.newFixedThreadPool(3);
//3.使用线程池ExecutorService中的方法submit,获取线程执行线程任务
//new Thread(new RunnableImpl()).start();
es.submit(new RunnableImpl());//pool-1-thread-1线程正在执行线程任务!
es.submit(new RunnableImpl());//pool-1-thread-3线程正在执行线程任务!
es.submit(new RunnableImpl());//pool-1-thread-2线程正在执行线程任务!
es.submit(new RunnableImpl());//pool-1-thread-3线程正在执行线程任务!
//使用匿名内部类:简化Runnable接口的实现类对象
es.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程正在执行线程任务!");
}
});
/*
void shutdown() 用于销毁线程池
相当于把鱼缸打碎了,就不能在使用了
线程池一旦被销毁,就不能在使用了
*/
//es.shutdown();
//es.submit(new RunnableImpl());//RejectedExecutionException:拒绝访问异常
}
}
package com.itheima.demo01ThreadPool;
//2.创建一个Runnable接口的实现类,重写run方法,设置线程任务(匿名内部类简化)
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程正在执行线程任务!");
}
}
4.使用线程池执行Callable接口的线程任务(重点)
package com.itheima.demo01ThreadPool;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.*;
/*
使用线程池执行Callable接口的线程任务(重点)
java.util.concurrent.Callable<V>接口
Callable 接口类似于 Runnable,两者都用用于创建一个线程任务
但是 Runnable 不会返回结果,Callable有返回结果
Callable接口中的方法
V call() 计算结果,如果无法计算结果,则抛出一个异常。
call方法是一个有返回值的方法,返回值的类型使用的是接口上的泛型
接口使用什么泛型,call方法就返回一个什么类型的值
Callable<Integer>==>call方法就返回一个Integer类型的数据
Callable<String>==>call方法就返回一个String类型的数据
-------------------------------------------------------------------------
<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
当我们使用submit方法执行Callable接口的线程任务,会把call的返回值存储到Future对象中
我们就需要从Future对象中,在取出call方法的返回值来使用
-------------------------------------------------------------------------
使用步骤(重点):
1.使用线程池工厂类Executors中的静态方法newFixedThreadPool,创建一个包含指定线程数量的线程池
2.使用线程池ExecutorService中的方法submit,执行Callable接口的线程任务
3.从submit方法的返回值Future对象中取出call方法的返回值
*/
public class Demo02ThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//1.使用线程池工厂类Executors中的静态方法newFixedThreadPool,创建一个包含指定线程数量的线程池
ExecutorService es = Executors.newFixedThreadPool(3);
//2.使用线程池ExecutorService中的方法submit,执行Callable接口的线程任务
Future<Integer> f1 = es.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
//返回一个0-9之间的随机整数(线程任务)
//Random r = new Random();
//int n = r.nextInt(10);
//return n;
return new Random().nextInt(10);