目录
一、Thread 类的子类
/*
1.建立Thread子类,重写run()方法
2.执行 子类对象.start()
*/
public class Demo1 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
//2.执行 子类对象.start()
myThread.start();
for(int i=0;i<10;i++){
System.out.println("线程"+Thread.currentThread().getName()+"执行了"+i+"次");
}
}
}
//1.建立Thread子类,重写run()方法
class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("线程"+this.getName()+"执行了"+i+"次");
}
}
}
每个线程都有自己的栈空间,但共用堆空间
二、实现 Runnable 接口
/*
1.实现Runnable接口
2.创建线程,添加任务
3.启动线程
*/
public class Demo2 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
//2.创建线程,添加任务
Thread thread = new Thread(myRunnable);
//3.启动线程
thread.start();
for(int i=0;i<10;i++){
System.out.println("疑是地下霜"+i);
}
}
/**
* 1.实现Runnable接口
*/
static class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("床前明月光"+i);
}
}
}
}
Runnable接口的优势:
- 通过创建任务,然后给线程分配的方式来实现多线程,更适合多个线程同时执行相同任务的情况
- 可以避免单继承所带来的局限性
- 任务与线程本身是分离的,提高程序的健壮性
- 线程池技术接受Runnable类型的任务,不接受Thread类型的线程
三、带返回值的线程Callable<V>接口
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
//创建任务
FutureTask<String> futureTask = new FutureTask<>(myCallable);
//先启动线程,添加任务
new Thread(futureTask).start();
//V get();主线程等待子线程执行,返回结果
System.out.println(futureTask.get());
//如果不需要获取子线程返回值,不实用get()方法,就与普通的线程创建方法想同
for (int i=0;i<10;i++){
System.out.println("疑是地上霜"+i);
}
}
/**
* 实现Callable<V> 接口
* 重写 V call() 方法 类似于Runnable接口的 void run()方法
*/
static class MyCallable implements Callable<String>{
@Override
public String call() throws Exception {
for (int i=0;i<10;i++){
System.out.println("床前明月光"+i);
}
return "锄禾日当午,汗滴禾下土";
}
}
}