实现多线程的几种方法

        Java虚拟机(Java Virtual Machine,JVM,是运行所有Java程序的抽象计算机,是Java语言的运行环境)允许应用程序并发地运行多个线程。在Java语言中,多线程的实现一般有以下三种方法:

(1) 实现 Runnable 接口,并实现该接口的 run() 方法;

      ① 自定义类并实现 Runnable 接口,实现 run() 方法。

      ② 创建 Thread 对象,用实现 Runnable 接口的对象作为参数实例化该 Thread 对象。

      ③ 调用 Thread 的 start() 方法。

// 创建线程类
class MyThread implements Runnable{
    public void run(){
        System.out.println("Thread body ...");    // 线程方法体
    }
}

public class Test{
    public static void main(String args[]){
        MyThread thread = new MyThread();
        Thread th = new Thread(thread);
        th.start();    // 开启线程
    }
}

(2) 继承 Thread 类,重写 run() 方法;

       Thread本质上也是实现了 Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start()方法。start()方法是一个 native(本地) 方法,它将启动一个新线程,并执行 run() 方法(Thread中提供的 run() 方法是一个空方法)。这种方式通过自定义类直接 extends Thread,并重写 run() 方法,就可以启动新线程并执行自己定义的 run() 方法。需要注意的是,当 start() 方法调用后,并不是立即执行多线程代码,而是使得该线程变为可运行状态 (Runnable),至于什么时候运行多线程代码,是由操作系统决定的。

        如下所示是 Thread 的使用方法:

// 创建线程类
class MyThread extends Thread{
    public void run(){
        System.out.println("Thread body ...");    // 线程的方法体
    }
}

public class Test{
    public static void main(String args[]){
        MyThread thread = new MyThread();
        thread.start();    // 开启线程
    }
}

(3)  实现 Callable 接口,重写 call() 方法;

      Callable 对象实际是属于 Executor 框架中的功能类,Callable 接口与 Runnable接口类似,但是提供了比 Runnable 更强大的功能,主要表现为以下三点:

      ① Callable 可以在任务结束后提供一个返回值,Runnable 无法提供这个功能;

      ② Callable 中的 call() 方法可以抛出异常,而 Runnable 的 run() 方法不能抛出异常;

      ③ 运行 Callable 可以拿到一个 Future 对象,Future对象表示异步计算的结果。它提供了检查计算是否完成的方法。由于线程属于异步计算模型,所以无法从其他线程中得到方法的返回值,在这种情况下,就可以使用 Future 来监视目标线程调用 call()方法的情况,当调用 Future 的 get()方法以获取结果时,当前线程就会阻塞,直到 call() 方法结束返回结果。

        示例代码如下:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableAndFuture {
	// 创建线程类
	public static class CallableTest implements Callable<String>{
		@Override
		public String call() throws Exception {
			// TODO Auto-generated method stub
			return "Hello World !!!";
		}
	}
	
	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<String> future = threadPool.submit(new CallableTest());	//启动线程
		try {
			System.out.println("waiting thread to finish !!!");
			System.out.println(future.get()); 	//等待线程结束,并获取返回结果
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

以上程序运行结果如下所示:

在以上三种方式中,前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。当需要实现多线程时,一般推荐实现 Runnable 接口的方式,原因如下:首先,Thread 类定义了多种方法可以被派生类使用或重写,但是只有 run() 方法是必须被重写的,在 run() 方法中实现这个线程的主要功能。这当然是实现 Runnable 接口所需的同样的方法。而且,很多Java开发者认为,一个类仅在它们需要被加强或修改时才会被继承。因此,如果没有必要重写 Thread 类中的其他方法,那么通过继承 Thread 的实现方式与实现 Runnable 接口的效果相同,在这种情况下最好通过实现 Runnable 接口的方式来创建线程。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值