我们开发工程中经常使用到线程,在线程使用上,我们可能会有这样的场景:
-
伴随这一个业务产生一个比较耗时的任务,而这个业务返回并不需要等待该任务。那我们往往会启动一个线程去完成这个异步任务。
-
我们需要一个定时任务比如:定时清除数据,我们会起一个定时执行线程去做该任务。
上述问题比较简单,new一个线程然后去做这件事。但是我们常常忽略一个问题,线程异常了怎么办? 比如耗时任务我们只完成了一半,我们就异常结束了(这里不考虑事务一致性,我们只考虑一定要将任务完成)。又比如在清数据的时候,数据库发生断连。这时候我们会发现线程死掉了,任务终止了,我们需要重启整个项目把该定时任务起起来。
场景一解决思路:
package cn.merryyou.thread;/** * Created by 11 on 2017/7/5. */public class Plan { private SimpleTask task = new SimpleTask(); public static void main(String[] args) { Plan plan = new Plan(); plan.start(); } public void start(){ Thread thread = new Thread(task); thread.setUncaughtExceptionHandler((t, e) -> { System.out.println(e.getMessage()); start(); }); thread.start(); } static class SimpleTask implements Runnable{ private int task = 10; [@Override](https://my.oschina.net/u/1162528) public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+"--"+"启动"); while(task>0){ try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } if(System.currentTimeMillis()%3==0){ throw new RuntimeException("模拟异常"); } System.out.println(threadName+"--"+"执行task"+task); task--; } System.out.println(threadName+"--"+"正常终止"); } }}
输出:
Thread-0--启动Thread-0--执行task10Thread-0--执行task9Thread-0--执行task8模拟异常Thread-1--启动Thread-1--执行task7模拟异常Thread-2--启动模拟异常Thread-3--启动Thread-3--执行task6模拟异常Thread-4--启动Thread-4--执行task5模拟异常Thread-5--启动Thread-5--执行task4模拟异常Thread-6--启动Thread-6--执行task3模拟异常Thread-7--启动Thread-7--执行task2Thread-7--执行task1Thread-7--正常终止
线程池实现的方式:
package cn.merryyou.thread;import sun.java2d.pipe.SpanShapeRenderer;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;/** * Created by 11 on 2017/7/5. */public class Plan2 { private Plan.SimpleTask task = new Plan.SimpleTask(); private MyFactory factory = new MyFactory(task); public static void main(String[] args) { Plan2 plan2 = new Plan2(); ExecutorService pool = Executors.newSingleThreadExecutor(plan2.factory); pool.execute(plan2.task); pool.shutdown(); } class MyFactory implements ThreadFactory { private Plan.SimpleTask task; public MyFactory(Plan.SimpleTask task) { super(); this.task = task; } [@Override](https://my.oschina.net/u/1162528) public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setUncaughtExceptionHandler((t, e) -> { ExecutorService pool = Executors.newSingleThreadExecutor(new MyFactory(task)); pool.execute(task); pool.shutdown(); }); return thread; } }}
输出:
Thread-0--启动Thread-0--执行task10Thread-1--启动Thread-1--执行task9Thread-1--执行task8Thread-1--执行task7Thread-2--启动Thread-2--执行task6Thread-3--启动Thread-3--执行task5Thread-3--执行task4Thread-3--执行task3Thread-3--执行task2Thread-3--执行task1Thread-3--正常终止
定时任务ScheduledExecutorService 实现方式:
package cn.merryyou.thread;import java.util.concurrent.*;/** * Created by 11 on 2017/7/5. */public class Plan3 { private SimpleTask task = new SimpleTask(); public static void main(String[] args) { Plan3 plan = new Plan3(); start(plan.task); } public static void start(SimpleTask task){ ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor(); ScheduledFuture future = pool.scheduleAtFixedRate(task, 0, 1000, TimeUnit.MILLISECONDS); try { future.get(); }catch (InterruptedException | ExecutionException e){ System.out.println(e.getMessage()); start(task); }finally { pool.shutdown(); } } class SimpleTask implements Runnable{ private volatile int count = 0; [@Override](https://my.oschina.net/u/1162528) public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+"--启动"); try{ Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); } if(System.currentTimeMillis()%3==0){ throw new RuntimeException("模拟异常"); } System.out.println(threadName+"--执行task"+count); count++; System.out.println(threadName+"--正常终止"); } }}
输出:
pool-1-thread-1--启动pool-1-thread-1--执行task0pool-1-thread-1--正常终止pool-1-thread-1--启动java.lang.RuntimeException: 模拟异常pool-2-thread-1--启动java.lang.RuntimeException: 模拟异常pool-3-thread-1--启动java.lang.RuntimeException: 模拟异常pool-4-thread-1--启动java.lang.RuntimeException: 模拟异常pool-5-thread-1--启动java.lang.RuntimeException: 模拟异常pool-6-thread-1--启动java.lang.RuntimeException: 模拟异常pool-7-thread-1--启动java.lang.RuntimeException: 模拟异常pool-8-thread-1--启动pool-8-thread-1--执行task1pool-8-thread-1--正常终止pool-8-thread-1--启动pool-8-thread-1--执行task2pool-8-thread-1--正常终止pool-8-thread-1--启动......
参考链接: