多线程------创建多线程的三种方式

①创建一个继承于java.lang.Thread的类

public class MyThread1 extends Thread{
	// 在run方法中实现此线程需要实现的功能
	@Override
	public void run() {
		System.out.println("线程名字:"+Thread.currentThread().getName() + "\t线程ID:" 
					 + Thread.currentThread().getId());
	}
}
//测试类
public class MyThreadTest {
	public static void main(String[] args) {
		// 创建自定义线程
		MyThread1 myThread1 = new MyThread1();
		// 开启线程
		myThread1.start();
	}
}
// 输出 :线程名字:Thread-0	线程ID:10

②实现java.lang.Runnable接口,重写run()方法,然后使用Thread类来包装

public class MyRunnable implements Runnable{
   // 在run方法中实现此线程需要实现的功能
   @Override
   public void run() {
   	System.out.println("线程名字:"+Thread.currentThread().getName() + "\t线程ID:" 
   			 + Thread.currentThread().getId());
   }
}
//测试类
public class ThreadTest {
   public static void main(String[] args) {
   	// 创建MyRunnable
   	MyRunnable myRunnable = new MyRunnable();
   	// 用Thread 包装一下myRunnable
   	Thread thread = new Thread(myRunnable);
   	// 开启线程
   	thread.start();
   }
}
// 输出 :线程名字:Thread-0	线程ID:10
  1. 这两种方式实现多线程的方式都是围绕着Thread类展开的,第一种方式实现线程是继承于java.lang.Thread类,然后实现run方法,最终调用Thread类中的start方法启动线程。而实现Runnable接口,则是把run写到了接口中,并由实现类实现run方法,然后再用Thread类对Runnable接口进行包装,然后在调用Thread中start方法启动线程。①②两种方式都是最终都是调用Thread中start方法进行启动线程。
  2. 两种方式在本质上没有明显的区别,但是在外观上有很大的区别,第一种方式是继承Thread类,由于Java是单继承,如果一个类继承了Thread类,那么就没办法继承其它的类了,在继承上有一点受制,有一点不灵活,第二种方式就是为了解决第一种方式的单继承不灵活的问题,所以平常使用就建议使用第二种方式。

③ 实现 java.util.concurrent.Callable,用java.util.concurrent.FutureTask类对其包装,然后再用java.lang.Thread类对java.util.concurrent.FutureTask的实现类进行包装

public class MyCallable implements Callable<Integer>{
   @Override
   public Integer call() throws Exception {
   	System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tstarting...");
       int sum = 0;
       for (int i = 0; i <= 100; i++) {
           sum += i;
       }
       Thread.sleep(5000);
       System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tover...");
       return sum;
   }
}

// 测试类
public class ThreadTest {
   public static void main(String[] args) throws InterruptedException, ExecutionException {
   	MyCallable myCallable = new MyCallable();
   	// 将Callable包装成FutureTask,FutureTask也是一种Runnable
   	FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
   	Thread thread = new Thread(futureTask);
   	thread.start();
   	// get方法会阻塞调用的线程
   	Integer res = futureTask.get();
   	System.out.println("线程执行结果:"+res);
   }
}
//Thread-0	10	Wed Apr 15 15:32:38 CST 2020 	starting...
//Thread-0	10	Wed Apr 15 15:32:43 CST 2020 	over...
//线程执行结果:5050
三种方式比较:
  • Thread: 继承方式, 不建议使用, 因为Java是单继承的,继承了Thread就没办法继承其它类了,不够灵活
  • Runnable: 实现接口,比Thread类更加灵活,没有单继承的限制
  • Callable: Thread和Runnable都是重写的run()方法并且没有返回值,Callable是重写的call()方法并且有返回值并可以借助FutureTask类来判断线程是否已经执行完毕或者取消线程执行
结论
  • 当线程不需要返回值时使用Runnable,需要返回值时就使用Callable,一般情况下不直接把线程体代码放到Thread类中,一般通过Thread类来启动线程
  • Thread类是实现Runnable,
  • Callable封装成FutureTask,FutureTask实现RunnableFuture,RunnableFuture继承Runnable,所以Callable也算是一种Runnable,
  • 所以三种实现方式本质上都是对Runnable实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值