1、继承Thread类
该方法的线程创建步骤:
1、创建一个继承自Thread类的子类
2、重写Thread类的run()方法 ----->run()方法里边实现线程操作
3、主线程main里边创建该子类的对象
3、使用子类对象名调用start()方法,开启线程
public class CreateThread01 {
static class Mythread extends Thread{
@Override
public void run() {
System.out.println("线程创建的第一种方法");
}
}
public static void main(String[] args) {
new Mythread().start();
}
}
2、实现Runnable接口
该方法的线程创建步骤 :
1、创建一个实现Runnable接口的类
2、实现类去实现Runnable接口中的抽象方法run()
3、创建实现类的对象
4、将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5、通过Thread类的对象调用start(),启动线程
6、调用当前线程的run()–>调用了Runnable类型的target的run()
static class MyRun implements Runnable{
@Override
public void run() {
System.out.println("线程创建的第二种方法");
}
}
public static void main(String[] args) {
new Mythread().start();
new Thread(new MyRun()).start();
}
方法一与方法二的比较:
在实际开发中,优先选择实现Runnable接口的方式
原因:
- Runnable接口可以多继承,没有单继承的局限性
- 实现的方式更适合处理多线程有共享资源的情况
相同点:两种方式都需要重写run()方法,将线程需要实现的逻辑声明在run方法里边
3、实现Callable接口
1、创建一个实现Callable接口的类
2、实现call方法,将线程需要实现的逻辑声明在call方法内
3、创建Callable接口实现类的对象
4、将该对象作为参数传递到Future task构造器中,创建Future Task的对象
5、将Future Task作为参数传递到Thread类的构造器中,创建Thread对象,并调用start方法
6、获取Callable中call方法的返回值
static class MyCall implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("线程创建的第四种方法");
return "线程创建的第四种方法";
}
}
public static void main(String[] args) {
new Mythread().start();
new Thread(new MyRun()).start();
new Thread(()->{
System.out.println("线程创建的第三种方法");
}).start();
Thread thread = new Thread(new FutureTask<String>(new MyCall()));
thread.start();
}
使用Callable接口创建线程的好处
1、call()方法有返回值
2、call()方法可以抛出异常,被外边的操作所捕获,获取异常的信息
3、Callable支持泛型
4、使用线程池
1、以方式二或方式三实现接口并创建对象
2、实现run()或call()方法
3、创建线程池
4、 调用线程池的execute方法,执行某个线程,参数是之前实现runnable或callable接口的对象
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(()->{
System.out.println("使用线程池创建线程");
});
executorService.shutdown();
}
//使用线程池调用线程
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> submit = executorService.submit(new MyCall());
String s = submit.get();
System.out.println(s);
使用线程池的好处:
1、提高响应速度(减少了创建新线程的时间)
2、降低资源消耗(重复利用线程池中的线程,不需要再创建)
3、便于线程管理
5、使用匿名类
public class Thread {
public static void main(String[] args) {
//匿名内部类
Thread thread=new Thread(new Runnable() {
//具体的业务代码
@Override
public void run() {
Thread t=Thread.currentThread();
System.out.println("线程为"+t.getName());
}
},"线程5");//给线程起名为线程4
thread.start();
}
}