博客源码:here
package thread;
public class Mythread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" mythread...");
}
public static void main(String[] args) {
Thread t1=new Mythread();
Thread t2=new Mythread();
Thread t3=new Mythread();
t1.start();
t2.start();
t3.start();
}
}
package thread;
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" mythread...");
}
public static void main(String[] args) {
MyRunnable r=new MyRunnable();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
}
package thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable{
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName()+" mythread...");
return "success";
}
public static void main(String[] args) {
MyCallable myCallable=new MyCallable();
FutureTask<String> futureTask=new FutureTask<String>(myCallable);
new Thread(futureTask).start();
//获取执行结果
try {
String str=futureTask.get();//会调用call()的执行结果
System.out.println("执行结果:"+str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现Runnable/Callable vs 继承Thread:
优点: 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类,而继承Thread的方式不能再继承其他类。在这种方式下,多个线程可以共享同一个 target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
缺点: 编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法;而继承Thread的方式不仅编程简单,直接使用 this 即可获得当前线程。
实现Runnable vs 实现Callable:
Callable的任务执行后可返回值,而Runnable的任务是不能返回值的;
Callable的方法可以抛出异常,Runnable的方法不可以;
运行Callable任务可以拿到一个Future对象,表示异步计算的结果,通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
Executor接口:
Executor 提供了一种思想:将任务提交和任务执行进行解耦。 用户只需要提交任务,提供 Runnable 对象,将任务的运行逻辑提交到执行器(Executor)中;至于任务如何执行、调度,由Executor进行处理。
ExecutorService接口:
增加了一些能力: 扩展了可异步跟踪执行任务生成返回值 Future 的方法,如 submit() 等方法。提供了管控线程池生命周期的方法,如 shutDown(),shutDownNow() 等。
AbstractExecutorService抽象类:
将执行任务的流程串联了起来, 保证下层的实现只需关注一个执行任务的方法即可。
ThreadPoolExecutor:
实现最复杂的运行部分 ,一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好的结合从而执行并行任务。
通过调用 Executors类中的静态工厂方法可创建不同的线程池 ,这些线程池的内部实现原理都是相同的,仅仅是使用了不同的工作队列或线程池大小。
注意:实际上并不推荐通过Executors类来创建线程池,而要通过ThreadPoolExecutor方法自定义创建,原因是Executors类提供的几种线程池有不同的短板,容易引起OOM、浪费资源的问题;而且这几种线程池把参数限定了,缺少了灵活性。
固定大小的线程池:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
大小为1的线程池:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
线程池的线程数可达到Integer.MAX_VALUE,线程空闲一定时间后会被销毁,使用SynchronousQueue等待队列,不会出现OOM。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ExecuteTest {
public static void main(String[] args) {
//创建一个线程池
ThreadPoolExecutor pool=new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
pool.execute(new Task1());
pool.execute(new Task2());
pool.execute(new Task3());
pool.shutdown();
}
}
class Task1 implements Runnable{
@Override
public void run() {
System.out.println("正在执行Task1");
}
}
class Task2 implements Runnable{
@Override
public void run() {
System.out.println("正在执行Task2");
}
}
class Task3 implements Runnable{
@Override
public void run() {
System.out.println("正在执行Task3");
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SubmitTest {
public static void main(String[] args) throws ExecutionException, InterruptedException{
//创建一个线程池
ThreadPoolExecutor pool=new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
//submit一个callable任务
Future<String> future=pool.submit(new Task(1));
//获取callable任务执行结果
while(!future.isDone()){
System.out.println("获取执行结果:"+future.get());
}
pool.shutdown();
}
}
class Task implements Callable<String>{
private int id;
public Task(int id){
this.id=id;
}
@Override
public String call() {
System.out.println("正在执行Task id:"+id);
return "success";
}
}
创建一个定时任务,每隔2s执行一次。
package schedule;
import java.text.SimpleDateFormat;
import java.util.*;
public class TimerTest {
public static final SimpleDateFormat FORMAT=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
//创建一个TimerTask
TimerTask timerTask=new TimerTask() {
@Override
public void run() {
System.out.println("执行任务:"+FORMAT.format(new Date()));
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
//创建Timer执行周期定时任务
System.out.println("现在是:"+FORMAT.format(new Date()));
Timer timer=new Timer();
//从现在开始,每间隔2s执行一次timerTask
timer.schedule(timerTask,new Date(), 2000);
}
}
使用ScheduledThreadPoolExecutor替换Timer可以解决单线程和异常导致终止的问题:
package schedule;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExecutorTest {
public static final SimpleDateFormat FORMAT=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
//创建多个TimerTask
TimerTask timerTask1=new TimerTask() {
@Override
public void run() {
System.out.println("执行任务1:"+FORMAT.format(new Date()));
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
TimerTask timerTask2=new TimerTask() {
@Override
public void run() {
System.out.println("执行任务2:"+FORMAT.format(new Date()));
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
//创建ScheduledThreadPoolExecutor执行周期定时任务
System.out.println("现在是:"+FORMAT.format(new Date()));
ScheduledThreadPoolExecutor pool=new ScheduledThreadPoolExecutor(2);
pool.scheduleAtFixedRate(timerTask1, 0, 1000, TimeUnit.MILLISECONDS);
pool.scheduleAtFixedRate(timerTask2, 0, 2000, TimeUnit.MILLISECONDS);
}
}
代码粘贴自here
//调用shutdown()方法关闭线程池
pool.shutdown();
try{
//等待60秒
if (!pool.awaitTermination(60, TimeUnit.SECONDS)){
//调用shutdownNow取消正在执行的任务
pool.shutdownNow();
//再次等待60秒,如果还未结束,可以再次尝试,或者直接放弃
if(!pool.awaitTermination(60, TimeUnit.SECONDS)){
System.err.println("线程池任务未正常执行结束");
}
}
}catch(InterruptedException ex){
//重新调用shutdownNow
pool.shutdownNow();
}
blog1:here
blog2:here
blog3:here
blog4:here