一、线程池
1、线程池的思想
之前的代码每次执行一次方法都需要开启一个新的线程,每个线程执行很短的时间就使用结束了,频繁的创建和销毁线程需要耗费很大的时间和空间。
线程池:提前创建多个线程对象放在池中,用的时候取出来使用,用完之后归还到线程池中,线程对象被反复使用,减低时间和空间的消耗。
2、线程池的好处
提高响应速度【用的时候直接从线程池拿出来用】
降低资源消耗【线程对象反复被使用】
提高线程对象的可管理性【线程对象放在线程池中方便管理】
3、线程池的使用
创建对象
Executors的方法:
public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。
(参数表示线程个数最大数量)
ExecutorService的方法:
public Future<?> submit(Runnable task) :执行一个任务
返回值Future接口:用来记录线程任务执行完毕后产生的结果。
示例代码
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println("线程开始执行了");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("线程执行结束了");
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test01 {
public static void main(String[] args) {
//使用线程池
//参数代表的是创建的线程对象个数
//在线程池内部会自动帮我们创建线程,不需要我们自己创建了
ExecutorService service = Executors.newFixedThreadPool(3);
RunnableImpl ri = new RunnableImpl();
//调用方法把代码交给线程池中的线程来执行
service.submit(ri);
service.submit(ri);
service.submit(ri);
service.submit(ri);
}
}
4、Callable开启多线程
功能
可以抛出异常
可以有返回值类型
示例代码
import java.util.concurrent.Callable;
public class CallableImpl implements Callable<Integer> {
@Override
public Integer call() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
public class Test01 {
public static void main(String[] args) throws Exception {
//使用线程池
//参数代表的是创建的线程对象个数
//在线程池内部会自动帮我们创建线程,不需要我们自己创建了
ExecutorService service = Executors.newFixedThreadPool(3);
CallableImpl ci = new CallableImpl();
//Callable只能用在线程池中执行
Future<Integer> future = service.submit(ci);
//获取Future里面的真实结果
Integer sum = future.get();
System.out.println(sum);
}
}
二、线程状态
1、线程状态
NEW : 新建状态
Runnable: 可运行状态
Blocked : 锁阻塞状态
Waiting : 无限等待状态
Timed Waiting : 计时等待状态
Terminated: 终止状态
2、状态转换图
以前没有统一规定时有说成五种状态,也有六中状态,但是现在,统一六种状态
三、等待唤醒机制
Object类的方法
wait() :让当前线程进入等待状态
notify() :唤醒一个正在等待的线程
注意: 这两个方法必须在同步里面使用锁对象调用,如果不使用锁对象调用就会出异常
这两个方法是定义在Object类中的方法,为什么要定义在Object类中?
答:这两个方法需要使用锁对象来调用,而锁对象可以是任意类型的对象,也就是说任意类型都需要调用者两个方法,所以就只能定义在Object类中。Object是所有类的父类,子类可以继承并使用父类的方法。
wait()等待和sleep()睡眠的区别:
wait()方法是释放锁然后等待
sleep()方法是抱着锁然后睡觉