1.Thread类和Runable接口

JDK提供了Thread和Runanle接让我们实现自己的线程类。

  • 继承Thread类,重写run()方法;
  • 实现Runable接口,实现run()方法

2.Thread常用的几个方法

currentThread():静态方法,返回对当前正在进行线程的引用;
start():开始调用线程的方法,java虚拟机会调用run()方法;
yield():当前线程愿意让出对当前处理器的占用;
sleep();使当前线程睡眠一段时间;
join():使当前线程等待另一个线程执行瓦尼比之后再执行,内部调用的是Object的wait()方法。

3.Thread类与Runable接口的比较

(1)java“单继承,多实现”的特性,Runable比Thread更灵活。
(2)Runable接口更符合面向对象,将县城进行单独封装;
(3)Runable接口降低了线程对象和线程任务的耦合性;
(4)使用线城时不需要Thread类的诸多方法,Runable接口更轻量级一些。
总结:优先使用Runable接口实现线程类。

4.Callable接口、Future接口与FutureTask类

使用Thread类和Runable创建的线程,执行的run()方法没有返回值。
JDK提供了Callable接口和Future接口为我们解决这个问题,这也是所谓的“异步”模型。

4.1Callable接口

Callable接口配合线程池工具ExecutorService使用,ExecuttorService调用submit()方法让callable线程执行,返货一个Future,通过Future的get得到这个返回值。
eg:

public static class MyThread implements Callable {
        @Override
        public Integer call() throws Exception {
            System.out.println("进入了callable-----------");
            return 222;
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService=Executors.newCachedThreadPool();
        MyThread thread=new MyThread();
        Future<Integer>  result= executorService.submit(thread);
        System.out.println(result.get());}

4.2 Future接口

future接口的全部方法

public abstract interface Future<V> {
    public abstract boolean cancel(boolean paramBoolean);
    public abstract boolean isCancelled();
    public abstract boolean isDone();
    public abstract V get() throws InterruptedException, ExecutionException;
    public abstract V get(long paramLong, TimeUnit paramTimeUnit)
            throws InterruptedException, ExecutionException, TimeoutException;
}

paramBoolean参数表示是否采取中断的方式取消执行。
cancel()方法是试图取消一个线程的执行。
如果为了让任务又能够取消的功能,就用callable代替runable.
入股哦为了任务有可取消性,但不需要返回结果,则可声明Feture<?>形式类型,返回null作为底层任务的结果。

public static class MyThread implements Callable {
        @Override
        public Future<?> call() throws Exception {
            System.out.println("进入了callable-----------");
            return null;
        }
    }
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        MyThread thread = new MyThread();
        Future<Integer> result = executorService.submit(thread);
        result.cancel(false);
    }

4.3 FutureTask类
FutureTask接口实现了RunableFuture接口,
RunableFuture同时继承了Runbale接口和Future接口。
FutureTask类的作用,实现了Future接口的方法直接共我饿们使用。

public static class MyThread implements Callable {
        @Override
        public Integer call() throws Exception {
            System.out.println("进入了callable-----------");
            return 111;
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
        executorService.submit(futureTask);
        System.out.println(futureTask.get());
        }

4.3FutureTask执行多任务计算的使用场景

利用FutureTask 和ExectutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,在异步获取子线程的执行结果。

public static class MyThread implements Callable<Integer> {
        private Integer result = 0;
        private String taskName = "";
        public MyThread(Integer initResult, String taskName) {
            result = initResult;
            this.taskName = taskName;
            System.out.println("生成子线程计算任务:" + taskName);
        }
        @Override
        public Integer call() throws Exception {
            for (int i = 0; i < 100; i++) {
                result = +i;
            }
            //休眠5秒
            Thread.sleep(5000);
            System.out.println("子线程计算任务:" + taskName + "执行完成");
            return result;
        }

    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Main initMain = new Main();
        //创建任务集合
        List<FutureTask<Integer>> taskList = new ArrayList<>();
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            //传入callable对象,创建FutureTask任务
            FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread(i, "" + i));
            taskList.add(ft);
            //提交给线程池任务
            executorService.submit(ft);
        }
        System.out.println("所有计算任务提交完毕");
        //统计线程计算结果
        Integer totalResult = 0;
        for (FutureTask<Integer> task : taskList) {
            totalResult = totalResult + task.get();
        }
        executorService.shutdown();
        System.out.println("多任务的计算结果为:" + totalResult);
        }

4.4 FutureTask在高并发下确保任务只执行一次

用ConcurrentHash,可以避免加锁的情况。此例子避免了鱿鱼板并发带来的重复创建及锁的出现。

public class Main extends Thread {
    private Map<String, FutureTask<Integer>> taskPool = new ConcurrentHashMap<String, FutureTask<Integer>>();
    public Integer getTask(String key) throws ExecutionException, InterruptedException {
        FutureTask<Integer> task = taskPool.get(key);
        System.out.println("task=:"+task);
        if (task != null) {
            return task.get();
        } else {
            Callable<Integer> callable = new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return creatKey();
                }
            };
            FutureTask<Integer> newTask = new FutureTask<Integer>(callable);
            task = taskPool.putIfAbsent(key, newTask);
            if (task == null) {
                task = newTask;
                task.run();
            }
        }
        return task.get();
    }
    private Integer creatKey() {
        return 122;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Main main = new Main();
        System.out.println("result=:" + main.getTask("qww"));
    }