【多线程】Java创建多线程的4种方法

一:继承Thread类

  1. 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体
  2. 创建Thread子类的实例,即创建了线程对象
  3. 调用线程对象的start()方法来启动该线程
public class ExtendsThreadTest extends Thread{
	//重写run方法
	@Override
	public void run(){
		System.out.println(Thread.currentThread().getName());
		或
		System.out.println(getName());
		或
		System.out.println(this.getName());
	}
	
	public static void main(String[] args){
		//创建两个线程
		new ExtendsThreadTest().start();
		new ExtendsThreadTest().start();
	}
}

  Thread实现Runnable接口:class Thread implements Runnable
  Thread实现的Runnable的run方法是下面这样的,可以看出run方法实现非常简单,所以我们如果想让线程实现我们要做的事情,可重写run方法:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

二:实现Runnable接口

  1. 定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
  2. 创建 Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
  3. 调用线程对象的start()方法来启动该线程
public class ImplementsRunnableTest implements Runnable {

	//实现接口的run方法
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName());

	}

	public static void main(String[] args){
		ImplementsRunnableTest t = new ImplementsRunnableTest();
		//创建两个线程
		new Thread(t).start();
		new Thread(t).start();
	}

}

三:通过Callable和Future创建

  1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值
  2. 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,它实现了RunnableFuture接口,而RunnableFuture又同时实现了Future和Runnable接口,所以简介的实现了Runnable接口
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程
  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
public class ThirdThreadTest implements Callable<String> {

	@Override
	public String call() throws Exception {		
		return Thread.currentThread().getName();
	}

	public static void main(String[] args){
		//创建callable实现类实例
		ThirdThreadTest t = new  ThirdThreadTest();
		//使用FutureTask类来包装Callable对象
		FutureTask<String> ft1= new FutureTask<String>(t);
		FutureTask<String> ft2= new FutureTask<String>(t);
		new Thread(ft1).start();
		new Thread(ft2).start();
		 try {
			System.out.println(ft1.get());
			System.out.println(ft2.get());
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

四:通过所线程池

  1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值
  2. 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口)
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程
  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
public class ThreadPoolTest implements Runnable {

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName());
		
	}
	
	public static void main(String[] args){
		//创建线程池
		ExecutorService e = Executors.newFixedThreadPool(5);
		ThreadPoolTest t = new ThreadPoolTest();
				
		for(int i=0;i<3;i++){
			//为线程池分配任务
//			Future f = e.submit(t);
//			if (f.get() == null ){
//				System.out.println("执行完成");
//			}
			e.execute(t);
		} 
		//关闭线程池
		e.shutdown();		
	}
}

创建线程可以使用submit()或execute(),两者区别为:

  • submit()有返回值,execute()无返回值void execute(Runnable command);,利用Future .get()去的线程执行的结果,如果等于null,表示执行成功
  • submit()方法有3种参数类型,execute只有1种参数
void execute(Runnable command);

1. <T> Future<T> submit(Callable<T> task);
2. <T> Future<T> submit(Runnable task, T result);
3. Future<?> submit(Runnable task);

四:四种创建方法的区别

  • 使用创建Thread子类的方法,只能继承Thread类,所以不能再继承其它父类了,而实现了Runnable接口或Callable接口,还可继承其它的类,更加面向对象
  • Runnable接口或Callable接口时,要访问当前线程必须使用Thread.currentThread()方法,而继承Thread直接使用this即可获得当前线程
  • Callable任务执行后有返回值,而Runnable没有返回值
  • call方法可抛出异常,而run方法不可以

总结

  • 其实归根到底,所有的实现方法都是实现Runnable接口创建线程
  • 只有在启动线程的start方法时,才有执行线程要完成的任务,即run方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值