a)
通过继承
Thread
类
//①.继承Thread类
public class DemoA extends Thread{
/*
1.为什么书写的是run()方法,调用的却是start方法
2.为什么调用的是start方法,执行的却是run方法
3.为什么a1的run方法未执行完毕,a2的run方法就执行了
*/
//②.重写run方法 当run方法被执行时,线程进入运行状态
public void run() {
for (int i = 0; i < 30; i++) {
//获取到当前运行的线程名称
String threadName=Thread.currentThread().getName();
System.out.println(threadName+":"+i);
}
//run方法全部执行完毕后,线程进入死亡状态,释放当前线程对象
}
public static void main(String[] args) {
//产生对象 当产生一个线程类型的对象时,进入了新建状态
DemoA a1=new DemoA();
DemoA a2=new DemoA();
//当线程对象调用start方法时,线程进入就绪状态
//调用了a1的start方法
a1.start();//准备就绪,只等待CPU执行
a2.start();
}
/*
线程的生命周期
新建、就绪、运行和阻塞、死亡
*/
}
b)
通过实现
Runnable
接口
//①.实现Runnable接口
public class DemoB implements Runnable {
//②.重写run方法
public void run() {
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
public static void main(String[] args) {
//这个时候并不是新建状态,并不是一个线程对象
DemoB b1=new DemoB();
DemoB b2=new DemoB();
// 产生2个线程去包装这两个任务b1,b2
// 新建状态
Thread t1=new Thread(b1);
Thread t2=new Thread(b2);
t1.start();
t2.start();
}
}
c)
通过
Callable
和
Future
创建线程
i.
创建
Callable
接口的实现类,并实现
call()
方法,该
call()
方法将作为
线程执行体,并且有返回值
(
类似于
run()
方法
)
。
ii.
创建
Callable
实现类的实例,使用
FutureTask
类来包装
Callable
对象,
该
FutureTask
对象封装了该
Callable
对象的
call()
方法的返回值。
iii.
使用
FutureTask
对象作为
Thread
对象的
target
创建并启动新线程。
iv.
调用
FutureTask
对象的
get()
方法来获得子线程执行结束后的返回值
//①.实现一个Callable接口
public class DemoC implements Callable {
//②.重写call方法 返回一个结果 其余方法和run相同
public Object call() throws Exception {
int sum=0;
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName());
sum+=i;
}
return "1到20之和:"+sum;
}
public static void main(String[] args) throws Exception {
DemoC c1=new DemoC();
DemoC c2=new DemoC();
FutureTask ft1=new FutureTask(c1);
FutureTask ft2=new FutureTask(c2);
Thread t1=new Thread(ft1);
Thread t2=new Thread(ft2);
t1.start();
t2.start();
// 获取到返回结果
Object result1 = ft1.get();
Object result2 = ft2.get();
System.out.println(result1);
System.out.println(result2);
}
}