java创建线程的方式

# 首先看java是怎么执行多线程的


    @Override
    public void run() {
        Runnable task = holder.task;
        if (task != null) {
            Object bindings = scopedValueBindings();
            runWith(bindings, task);
        }
    }


    public void start() {
        synchronized (this) {
            // zero status corresponds to state "NEW".
            if (holder.threadStatus != 0)
                throw new IllegalThreadStateException();
            start0();
        }
    }
    private native void start0();

> 可以看到,真正创建线程的代码是native的。这里其实就是执行当前Thread的run方法里的内容。

>> 当没有重写run时就得有一个Runnable的任务

# java创建线程的方式

1. 继承Thread类,重写run方法

2. 使用Runnable作为Thread的构造器参数

3. 使用FutureTask作为Thread的构造器参数,FutureTask其实也是Runnable的子接口

4. 使用线程池 但是这个的意思其实不是创建新线程了,而是使用将任务提交到线程来执行。ExecutorService的submit会返回Future。

5. CompletableFuture

## 1. 继承Thread类,重写run方法

> 先看Thread里的run

    @Override
    public void run() {
        Runnable task = holder.task;
        if (task != null) {
            Object bindings = scopedValueBindings();
            runWith(bindings, task);
        }
    }

final Runnable task;

执行的是传进来的Runnable的task

如果没有task当然就不执行啦,所以要重写run方法,因为start的时候会新建一个真正的线程来执行run里的代码

## 2. 使用Runnable作为Thread的构造器参数

 Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("Runnable Thread : "+i);
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){}
                }
            }
        });
        thread.start();

改成lamda


        Thread thread = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("Runnable Thread : "+i);
                try {
                    Thread.sleep(1000);
                }catch (Exception e){}
            }
        });

## 3. FutureTask+Callable 使用FutureTask作为Thread的构造器参数,FutureTask其实也是Runnable的子接口

        Thread thread2 = new Thread(futureTask);
        thread2.start();
        String result = futureTask.get();
        System.out.println(result);

而FutureTask构造器里传入Callable对象,线程执行后,可以通过FutureTask的get来获取Callable的执行结果返回值。

        FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                for (int i = 0; i < 10; i++) {
                    System.out.println("Callable Thread : "+i);
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){}
                }
                return "Callable Thread Done";
            }
        });

//

### FutureTask

   public V get() throws InterruptedException, ExecutionException{}

   public V get(long timeout, TimeUnit unit){}

阻塞, 可以设置超时时间。其实超过时间了线程还是在运行,只不过读取的这个事件不再阻塞了。

5.

    CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
        System.out.println("in future");
        return "future end";
    });
    System.out.println("in main");
    String s = future.get();
    System.out.println(s);