第一种方式,直接继承Thread类,重写run方法,最为简单:
/**
* 实现的第一种方式就是继承自Thread类
*/
class MyThread extends Thread{
@Override
public void run(){
for(int i = 0 ; i <= 1000 ; i++){
System.out.println("线程-----"+ this.getId() + "------输出:" + i);
}
}
}
public class ThreadImpl1Test {
public static void main(String[] args){
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
}
}
好处:简单,易看懂,能在方法中直接使用this来调用继承的方法。
缺点:没有面向接口编程,没有体现依赖倒置原则。
第二种方式,实现Runable接口。
/**
* 实现的第二种方式就是实现Runable接口
* 这种实现方式有好处也有坏处。
* 好处:接口能多实现,并且这样实现能继承一个其他的接口
* 坏处:不能直接使用this。来获取线程id和线程名了,而是要使用Thread.currentThread().getId()
*/
class MyThread implements Runnable{
@Override
public void run(){
for(int i = 1 ; i <= 1000 ; i++){
System.out.println("线程-----" + Thread.currentThread().getId() + Thread.currentThread().getName() +"------输出:" + i);
}
}
}
public class ThreadImpl2Test {
public static void main(String[] args){
MyThread thread = new MyThread();
Thread thread1 = new Thread(thread);
Thread thread2 = new Thread(thread);
thread1.start();
thread2.start();
}
}
优点:执行体的代码可以复用,面向接口编程体现依赖倒置原则,实现类可以继承一个其他的类
缺点:不能通过this获取线程号,而是要通过Thread.currentThread()来获取线程信息。
第三种方式:实现Callable接口,使用Future接口实现类收成target传入具体线程
/**
* 实现的第三种方式就是实现 Callable<V> 接口,其中V是call()方法的返回值类型
*/
class MyThread implements Callable<Long>{
@Override
public Long call() throws Exception {
long sum = 0L;
for(long i = 1 ; i <= 1000L ; i++){
System.out.println("线程-----" + Thread.currentThread().getId() + Thread.currentThread().getName() +"------加了:" + i);
sum = sum + i;
}
return sum;
}
}
public class ThreadImpl3Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread thread = new MyThread();
FutureTask<Long> result1 = new FutureTask<>(thread);
FutureTask<Long> result2 = new FutureTask<>(thread);
Thread thread1 = new Thread(result1);
Thread thread2 = new Thread(result2);
thread1.start();
thread2.start();
Long sum1 = result1.get();// 获取返回值
Long sum2 = result2.get();// 获取返回值
System.out.println(sum1);
System.out.println(sum2);
}
}
优点:call()能抛出异常,有返回值。能通过Future对象看运行状态。