Java使用Thread类代表线程
有三种方法可以创建一个线程
1.继承Thread类
定义一个Thread类的子类并重写run()方法
run()方法的方法体就是线程需要完成的任务,称作线程执行体
创建该类的实例即创建了线程对象
2.实现Runnable接口
定义一个类实现Runnable接口并重写run()方法
run()方法仍然是线程执行体
该类的实例本身并不是线程
将该类的实例作为Thread类创建对象的参数
由Thread类创建的对象才是真正的线程对象
3.实现Callable接口
定义一个类实现Callable接口并重写call()方法
call()方法作为线程执行体,且call()有返回值
创建一个FutureTask类对象封装该类对象的call方法
该类的实例及FutureTask类对象本身并不是线程
将FutureTask类的对象作为Thread类创建对象的参数
由Thread类创建的对象才是真正的线程对象
三种方式的对比
后两种方式的区别在于第三种方式定义的方法有返回值,并且可以声明抛出异常,其余基本相同
第一种方式与后两种的比较如下:
第一种方式
优点:
实现简单,由于直接继承Thread类,需要访问当前线程只需要使用this
缺点:
继承了Thread类,不能再继承其他父类
后两种方式
优点:
只是实现了接口,还可以继承其他的父类
多个线程对象可以共享同一个Runnable实现类的对象或Callable实现类的对象
确定:
实现相对复杂,需要访问当前线程必须使用Thread.currentThread()方法
//继承Thread类
public class FirstThread extends Thread{
private int i=0;
@Override
// 重写run方法,run是线程执行体
public void run(){
for(; i<10; ++i)
// Thread类的getName()方法返回该线程的名字
System.out.println(getName()+" "+i);
}
public static void main(String[] args){
new FirstThread().start();
new FirstThread().start();
}
}
//实现Runnable接口
public class SecondThread implements Runnable {
private int i=0;
@Override
// 重写run方法,run仍是线程执行体
public void run() {
for(; i<100; ++i)
System.out.println(Thread.currentThread().getName()+" "+i);
}
public static void main(String[] args){
SecondThread st = new SecondThread();
new Thread(st).start();
new Thread(st).start();
}
}
//实现Callable接口
public class ThirdThread implements Callable<Integer>{
private int i=0;
@Override
// 重写call方法,作为线程执行体
public Integer call(){
for(; i<1000; ++i)
System.out.println(Thread.currentThread().getName()+" "+i);
return i;
}
public static void main(String[] args){
ThirdThread tt = new ThirdThread();
// FutureTask封装了Callable对象的call方法
FutureTask<Integer> task = new FutureTask<Integer>(tt);
FutureTask<Integer> task2 = new FutureTask<Integer>(tt);
// FutureTask对象作为Thread创建对象的参数
new Thread(task).start();
new Thread(task2).start();
try{
System.out.println(task.get());
} catch(Exception e){
e.printStackTrace();
}
}
}
第一种方式创建的两个线程是完全独立的两个对象
所以它们各自有一个私有的 i ,并不受另外一个影响
而后两种方式,使用同一个Runnable实现类的对象或Callable实现类的对象创建的两个线程对象
它们是共享这个Runnable实现类的对象或Callable实现类的对象的
所以它们的 i 是互相会影响的