线程是运行中的程序的调度单位,多线程问题可以理解为多任务的并行处理问题,因此更多牵涉同步和异步问题;

进程与线程的区别

进程拥有自己的一整套变量,线程需要共享变量。

线程的实现方法

第一种实现方法

(1)创建一个Runnable对象;
(2)用Runnable对象创建一个线程;
(3)启动线程;

Runnable runnable = new Runnable({
            @Override
            public void run() {
                System.out.println("finish---in ---runnable");
            }
        });
Thread thread = new Thread(runnable);
thread.start();

第二种实现方法

(1)新建一个继承于Thread的类MyThread
(2)新建一个MyThread对象;
(3)启动线程;

MyThread.java

public class MyThread extends Thread{

    String tag;
    public MyThread(String tag) {
        this.tag = tag;
    }

    @Override
    public void run() {
        System.out.println("finish---in ---" + tag);
    }   
}
MyThread myThread = new MyThread("MyThread");
myThread.start();

第三种实现方法

(1)新建一个实现了Runnable的接口MyRunnable;
(2)用新建的Runable对象新建一个MyThread对象;
(3)启动线程;

MyRunnable.java

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("finish---in ---MyRunnable");
    }
}
Thread thread = new Thread(new MyRunnable(){});
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
thread.start();

第四种实现方法

(1)使用Callable接口和FutureTask创建线程;创建实现Callable接口的类,并实现call();
(2)使用FutureTask类包装callable实现类的对象,最后将FutureTask对象作为Thread对象的
target;
(3)启动线程;

FutureTask<Integer> ft = 
                new FutureTask<Integer>(new Callable<Integer>() {
                    @Override
                    public Integer call() throws Exception {
                        return 10;
                    }
                });
        Thread thread = new Thread(ft);
        thread.start();

        try {
            Integer value = ft.get(1000, TimeUnit.MILLISECONDS);
            System.out.println(value.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

FutureTask
一个FutureTask可以用来包装一个Callable或Runnable对象. 因为FutureTask实现了Runnable接口, a一个FutureTask能够被提交到Executor去执行。

第五种方法

(1)使用Runnable和FutureTask创建线程;
(2)将FutureTask对象作为Thread对象的target;
(3)启动线程;

FutureTask<Integer> ft = 
                new FutureTask<Integer>(new MyRunnable(),100);//第二个参数是返回值和<?>对应类型
        Thread thread = new Thread(ft);
        thread.start();
        try {
            Integer value = ft.get(1000, TimeUnit.MILLISECONDS);
            System.out.println(value.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

区分Runnable,Callable,Future

Runnable

无返回值的异步任务

Callable

有返回值的异步任务,这是一个功能性接口,因此一个lambda表达式或方法参考可以作为赋值的目标。
一个task,可能返回一个结果,也可能会抛出一个异常;实现该接口的类定义一个不带参数的方法call,Callable接口类似于Runnable,都是设计给可能被另一个线程执行的类的实例。Runnable没有返回值,也不会抛出一个已检查异常。

Future

用来代表异步计算的结果。提供方法以检查计算是否完成,等待其完成,并检索计算结果。只有当计算完成时,才能得到结果,如果必要的话,就让它处于阻塞态,直到它到达就绪态。取消通过取消方法执行。提供其他方法以确定任务是否正常完成或被取消。一旦计算完成,计算不能被取消。如果你想用Future为了可取消性但是为了提供一个可用的结果, 你可以声明Future