一. 类继承Thread类创建线程
/**
*继承Thread类创建线程的方式
*/
public class MyThreadExtendThread extends Thread{
private int i;
//重写Thread的run方法来创建用户线程类的执行体
@Override
public void run() {
//迭代输出0到100的数字
for(;i<100;i++){
System.out.println(getName()+" "+i);
}
}
//main主线程
public static void main(String[] args){
for (int i=0;i<100;i++){
//非直接继承类的线程获得线程name需要使用Thread.currentThread().getName()
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//创建第一个用户线程,start()启动线程
new MyThreadExtendThread().start();
//创建第二个用户线程,start()启动线程
new MyThreadExtendThread().start();
}
}
}
}
二. 实现runnable接口创建线程
/**
* 实现runnable接口创建线程
* Created by jeker on 17-6-25.
*/
public class MyThreadImplementRunable implements Runnable {
private int i;
//实现Runnable接口的run()方法来创建用户线程的执行体
@Override
public void run() {
//迭代输出0到100的数字
for (;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
//main主线程
public static void main(String[] args){
for (int i =0 ;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//创建用户线程类实例
MyThreadImplementRunable myThreadImplementRunable = new MyThreadImplementRunable();
//以用户线程类的实例作为Thread的target来创建thrad对象,并制定线程名称,即线程对象
new Thread(myThreadImplementRunable,"线程1").start();
new Thread(myThreadImplementRunable,"线程2").start();
}
}
}
}
三.使用callable和future来创建线程
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* 使用callable和future创建线程(使线程执行后可以有返回值)
* Created by jeker on 17-6-25.
*/
public class CallableAndFuture {
//main主线程
public static void main(String[] args) {
//创建用户callable线程类,并实现实现callable方法
Callable<Integer> callable = new Callable<Integer>() {
//实现callable接口的call方法,来创建用户线程的执行体,并返回相应类型的值
@Override
public Integer call() throws Exception {
int i;
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i;
}
};
//使用futureTask对象来包装callable对象,该futureTask对象封装了callable的返回值
FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
for (int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//使用future作为thread的target来创建线程,实质上还是以callable来创建线程的
new Thread(futureTask,"futureTask1").start();
}
}
try {
//获取线程的返回值通过futuretask类
System.out.println("callable的返回值为:"+futureTask.get());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
三种创建线程方式的对比:
使用方式一:
优点:简单方便,获取线程信息不需要使用Thread.CurrentThread.getName(),可以直接以this.getName的方式获取.*
缺点:直接继承了Thread类,无法再继承其他类,扩展性差*
使用方式二:
优点:比较简洁,可以另外继承其他类扩展性好,同一个target创建的多个线程执行体共享一个成员变量.
缺点:获取线程相关信息的时候需要使用Thread.CurrentThread.getName().
使用方式三:
优点:线程执行体可以有返回值,可以另外继承其他类扩展性好,同一个target创建的多个线程执行体共享一个成员变量.
缺点:获取线程相关信息的时候需要使用Thread.CurrentThread.getName().
综上所述,推荐使用实现callable或runnable接口方式来创建线程.
关注笔者公众号,推送各类原创/优质技术文章 ⬇️