线程实现方式:
1.继承Thread类
2.实现Runnable接口
3.线程池
4.Callable
无论使用继承Thread类还是实现Runnable接口,还是使用线程池都无法解决这两个问题
/* run方法没有方法 返回值 run方法不能抛异常,如果想要解决异常,只能 用try-catch */ @Override public void run() { System.out.println("线程执行的run方法,没有返回值不能,不能抛异常"); } public static void main(String[] args) { new Thread(new MyThread()).start(); }
解决如上两个问题需要用到Callable,Callable和Runnable类似,在JUC包下,主要区别在于Callable中的call方法可以带返回值并且可以抛异常,如果需要执行Callable,需要Future实现类的支持,能够接受返回值结果,FutureTask是Future实现类
解决方案一:
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常"); return "callable"; } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable=new MyCallable(); //利用FutureTask执行Callable并且接受结果 FutureTask<String> stringFutureTask = new FutureTask<>(myCallable); //利用线程执行Task任务 new Thread(stringFutureTask).start(); //接收结果FutureTask.get会发生阻塞 System.out.println(stringFutureTask.get()); System.out.println("MyCallable执行完毕,返回值结果正确接收~"); } }
控制台结果:
方解决方案二:
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常"); return "callable"; } public static void main(String[] args) throws ExecutionException, InterruptedException { //方式二 MyCallable myCallable=new MyCallable(); //创建一个线程池 ExecutorService executorService= Executors.newFixedThreadPool(3); //创建线程执行额任务,接收任务结果 Future<String> future=executorService.submit(myCallable); //接收返回值 System.out.println(future.get()); System.out.println("方式二:线程池:MyCallable执行完毕,返回值结果正确接收"); //停止线程池 executorService.shutdown(); } }
控制台结果 :
Future.get()方法获取任务执行结果,该方法如果没有返回时,暂时处于阻塞状态
Future.get(Long timeOut,TimeUnit timeUnit)可以设置超时时间
Future.boolean isDone()如果线程结束,无论是正常结束还是任务终止都会返回true
Future.boolean isCanceller()如果任务完成前被取消则返回true
Future.boolean cancel(boolean flag),方法参数如果传入为true代表中断任务,如果任务中断成功,则返回值为true,
如果失败则为false
Future提供三种功能:1.中断任务cancel(true) 2.判断任务是否执行完成isDone()
3.编写测试代码:
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("Callable接口中重写的call方法,可以偶返回值并且可以抛异常"); return "callable"; } public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { //方式二 MyCallable myCallable=new MyCallable(); //创建一个线程池 ExecutorService executorService= Executors.newFixedThreadPool(3); //创建线程执行额任务,接收任务结果 Future<String> future=executorService.submit(myCallable); //中断任务 boolean cancel = future.cancel(true); if (cancel==true){ System.out.println("中断任务成功"); }else{ System.out.println(future.get(2000,TimeUnit.MILLISECONDS)); } //接收返回值 System.out.println(future.get()); System.out.println("方式二:线程池:MyCallable执行完毕,返回值结果正确接收"); //停止线程池 executorService.shutdown(); } }
控制台结果:
如果让手写Future模式应该怎么样定义
//FLAG相当于数据标识,如果放入数据成功,则返回为true,否则返回为false private static boolean FLAG=false; private String data; public synchronized void setData(String data) throws InterruptedException { Thread.sleep(2000); //赋值操作 this.data = data; FLAG=true; //唤起 notify(); } public synchronized String getData() { //如果获取数据失败 if(!FLAG){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } return data; } public static void main(String[] args) { MyFuture future=new MyFuture(); new Thread(()->{ try { future.setData("张三"); System.out.println(future.getData()); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); }