# 首先看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);