Java中实现线程原理:
Java中实现多线程的方式中最核心的就是 run()方法,不管何种方式其最终都是通过run()来运行。
新建线程时,我们常用new Thread(Runnable).start() 或者线程池搭载Runnable的两种方法来运行。

Java刚发布时也就是JDK 1.0版本提供了两种实现方式:
一个是继承Thread类,
一个是实现Runnable接口。
两种方式都是去重写run()方法,
在run()方法中去实现具体的业务代码。

继承Thread类和实现Runnable接口实现方式存在的弊端:
因为run()方法是没有返回值的,所以通过这两种方式实现的多线程的读是无法获得执行的结果。

为了解决以上两种实现方式存在的弊端而出现了第三种实现方法:
为了解决这个问题在JDK 1.5的时候引入一个Callable接口,根据泛型V设定返回值的类型,实现他的call()方法,可以获得线程执行的返回结果。虽然call()方法可以获得返回值,但它需要配合一个Future才能拿到返回结果,而这个Future又是继承了Runnable的一个接口。 通过查阅源码就可以发现Future的实现FutureTask其在做具体业务代码执行的时候仍是在run()里面实现的。

Java多线程实现方式的代码示例:
一.通过继承Thread类实现,但无法获得执行的结果
实现步骤:
①定义类继承Thread类,并重写Thread类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run()方法称为线程执行体。
②创建Thread子类的实例,即创建了线程对象。
②调用线程对象的start()方法来启动该线程。
例子:

public class XianChengThread {
	public static void main(String[] args) throws Exception {
		//方式一:通过继承Thread类实现
		//创建Thread类
	    Thread myThread1 = new MyThread();//线程名称:Thread-0
	    Thread myThread2 = new MyThread();//线程名称:Thread-1
	    Thread myThread3 = new MyThread();//线程名称:Thread-2
	    //调用start方法方可启动线程         
	  	//不能调用run()方法,run方法只是thread的一个普通方法,还是在主线程里执行。 
	    myThread1.start();
	    myThread2.start();
	    myThread3.start();
	  }
}

class MyThread extends Thread {
	  @Override
	  public void run() {
		  for(int i=0;i<3;i++){
			  System.out.println("Thread Name:" + Thread.currentThread().getName());
			}  	    
	    }
	}

执行结果:

java 实现线程的两种 java实现线程的方式_Java


二.通过实现Runnable接口实现,但无法获得执行的结果

实现步骤:

①定义类实现Runnable接口,并重写Runnable接口的run()方法,该run()方法的 方法体就代表了线程需要完成的任务。

②创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

②调用该Thread对象的start()方法来启动该线程。

例子:

public class XianChengRunnable {
	public static void main(String[] args) {
		//方式二,通过实现Runnable接口实现
		
		//创建Runnable实现类的实例 
	    MyRunnableThread myRunnable = new MyRunnableThread();
	    //创建Thread类,并把Runnable实现类的实例作为参数 
	    Thread myRunnableThread1 = new Thread(myRunnable);//线程名称:Thread-0
	    Thread myRunnableThread2 = new Thread(myRunnable);//线程名称:Thread-1
	    //start() 方法启动线程
	    myRunnableThread1.start();
	    myRunnableThread2.start();
	}
}
	class MyRunnableThread implements Runnable {
		  @Override
		  public void run() {
			// 实现Runnable接口的,无法直接使用getName()等方法        
			// 需要使用Thread.currentThread() 来获取到当前对象才行
			for(int i=0;i<5;i++){
				System.out.println("Thread Name:" + Thread.currentThread().getName());
			}
	  }
	}

执行结果:

java 实现线程的两种 java实现线程的方式_java 实现线程的两种_02


三.通过实现Callable接口实现,可获得执行的结果

例子:

public class XianChengCallable {

public static void main(String[] args) throws Exception {

//方式三:通过实现Callable接口来实现

//执行线程方法一:通过线程start()方法执行		 
	    //创建Callable实现类的实例 
	    Callable<String> myCallable = new MyCallableThread();		    
	    //创建一个 FutureTask,一旦运行就执行给定的 Callable。
	    FutureTask<String> futureTask = new FutureTask<>(myCallable);		    
	    //创建Thread类,并把创建的FutureTask实例作为参数 
	    Thread myCallableThread = new Thread(futureTask);
        //给线程名称赋值
	    myCallableThread.setName("通过实现Callable接口来实现的线程");		    
	    //通过start()方法执行
	    myCallableThread.start();
	    //FutureTask.get()方法可以等待计算完成,然后获取其结果。
	    System.out.println("获取线程的结果:" + futureTask.get());

	    
	    //执行线程方法二:通过线程池执行
	    ExecutorService executorService = Executors.newCachedThreadPool();
	    executorService.submit(futureTask);
	    executorService.shutdown();
	    System.out.println("获取通过线程池执行的结果:" + futureTask.get());
	  }
}
class MyCallableThread implements Callable {
 @Override
 //call()方法可以计算结果,如果无法计算结果,则抛出一个异常。
 public String call() throws Exception {
 return Thread.currentThread().getName();
 }
 }

执行结果:

java 实现线程的两种 java实现线程的方式_System_03


Callable与Runnable区别:

1.Runnable没有返回值,Callable可以获取返回值并返回
 2.Callable接口是带有泛型的,Callable。该泛型T,也是Callable返回值的类型;Callable接口需要实现的方法为call方法;
 Runnable接口需要实现的方法为run方法;
 3.Callable一般配合线程池的submit方法以及FutureTask使用,Runnable一般是配合new Thread或者线程池使用;
 4.Callable配合FutureTask,可以通过Future来控制任务执行、取消,查看任务是否完成等。Runnable也可以通过Future来实现以上功能,但方式不一样
Callable、Runnable 、Future与FutureTask的联系:
 Callable的价值,在Future上体现。
 Future是一个接口,而FutureTask是Future接口的官方唯一实现类。
 Future以及其实现类,是用于搭载Runnable或者Callable,执行任务、控制任务并能有效返回结果。FutureTask类不止实现了Future接口,还实现了其他的接口!如Runnable接口
 FutureTask有一个很重要的方法,是Done(),用于表示该FutureTask中的任务已执行完毕。