1.继承Thread类,重写run方法。
package com.ydlclass.thread;
public class UseThread extends Thread{
//线程创建的几种方式:1.继承Thread类,重写其run方法
@Override
public void run() {
System.out.println(2);
}
public static void main(String[] args) throws InterruptedException {
System.out.println(1);
new UseThread().start();//run方法与start方法的区别,start方法是启动线程的方式;如果使用run方法,结果是1,2,3.但是如果是start方法,那么可能的结果是1,3,2,
//原因是启动线程所需要的时间比较的多。
Thread.sleep(10);
System.out.println(3);
//启动main方法会启动一个主线程,于是打印了1,之后创建线程,由于线程启动需要时间,主线程执行完成代码之后就不再关照它;于是主线程打印了3.
//但是我们让主线程被延迟了10ms,主线程在被创建之后就没有谁先谁后之分了。
}
}
2.实现Runnable接口,实现run方法的方式创建线程。
3.使用匿名内部类的方式创建线程:
4.使用箭头函数(拉姆达表达式)创建线程:
package com.ydlclass.thread;
public class UseRunnable implements Runnable{
@Override
public void run() {
System.out.println(2);
}
public static void main(String[] args) {
System.out.println(1);
new Thread(new UseRunnable()).start();//注意start方法是Thread实例的方法,所以我们使用实现Runnable接口的方式创建得到线程并不存在start方法,
//这时这个线程的启动主要使用Thread类来启动,需要将Runnable的对象传输到Thread对象中,使用这个线程的有参构造来实现;
new Thread(new Runnable() {//这就是匿名内部类的方式创建一个线程
@Override
public void run() {
System.out.println(4);
}
}).start();
new Thread(()-> System.out.println(5)).start();//箭头函数创建一个线程。同时这样的创建方式我们也叫做拉姆达表达式创建线程
System.out.println(3);
}
}
5.以上创建线程的几种方式都是简单的打印一句话,但我们存在这样的业务,线程执行完之后可能需要返回一个值,这个值用于其他的使用中;
package com.ydlclass.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class UseCallable implements Callable<Integer> {//实现callable接口
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return 404;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> futureTask = new FutureTask<>(new UseCallable());//FutureTask类是一个用于接受其他线程返回值的一个类;
//这里为了能接受更多类型,所以使用了泛型来实现。此外,创建这个类的实例还需要一个callable类型的实例;
new Thread(futureTask).start();//由于start方法是Thread对象才拥有的实例方法,所以这个方法的使用必不可少的需要一个Thread对象;而thread对象需要传入一个runnable
//子类的对象,而futureTask这个类恰好是RunnableFuture的子类,而Runnable Future又恰好是Runnable的子类。
Integer integer = futureTask.get();//futureTask本质上就是一个接收UseRunnable进程的一个进程。
这个get()方法是一个阻塞方法,主函数阻塞不执行,一直等到get方法获取到值。
System.out.println(integer);
}
}