文章目录
1. 使用线程
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
继承Thread类
new Thread(){
@Override
public void run(){
while(true){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
实现Runnable接口
new Thread(new Runnable(){
public void run(){
while(true){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}).start();
实现Callable接口,有返回值,用FutureTask分装;
FutherTask ft = new FutherTask(new Callable(){
public Integer call(){
return '123'
}
});
Thread thread = new Thread(ft);
thread.start();
2. Executor
Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。
为什么要用线程池:
- 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
- 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务 器累趴下(每个线程需要大约 1MB 内存,线程开的越多,消耗的内存也就越大,最后死机)
Executors工厂类创建线程池
//创建固定大小的线程池
ExecutorService fPool = Executors.newFixedThreadPool(3);
//创建缓存大小的线程池
ExecutorService cPool = Executors.newCachedThreadPool();
//创建单一的线程池
ExecutorService sPool = Executors.newSingleThreadExecutor();
线程池使用
//异步执行,没有返回值
execute(Runnable);
//执行任务,返回一个futher,因为是Runnable对象,所以返回值为null
submit(Runnable);
//执行任务,返回一个futher
submit(Callable);
//invokeAny() 方法要求一系列的 Callable 或者其子接口的实例对象。调用这个方法并不会返回一个 Future,但它返回其中一个 Callable 对象的结果
invokeAny();
//invokeAll() 方法将调用你在集合中传给 ExecutorService 的所有 Callable 对象。invokeAll() 返回一系列的 Future 对象,通过它们你可以获取每个 Callable 的执行结果。
invokeAll(…);
3. 线程中断
通过调用线程的interrupt()方法来中断线程。
interrupt()方法仅仅是在当前线程中打了一个停止的标识将中断标志修改为true,并没有真正的停止线程。如果在此基础上进入堵塞状态(sleep(),wait(),join()) ,马上就会抛出一个InterruptedException,且中断标志被清除,重新设置为false,线程退出。
使用 shutdown()和 shutdownNow()可以关闭线程池
两者的区别:
shutdown只是将空闲的线程 interrupt() 了,shutdown()之前提交的任务可以继续执行直到结束。 shutdownNow 是 interrupt 所有线程, 因此大部分线程将立刻被中断。之所以是大部分,而不是全部 , 是因为 interrupt()方法能力有限。