线程创建Thread和Runnable

1.线程创建

  • 通过继承Thread类来创建线程,在执行时new MyThread() .start()
  • 通过实现Runnable接口来创建线程,在执行时 MyThread mt=new MyThread();  new  Thread(mt).start();
  • 通过ExecutorService和Callable实现有返回值的线程
  • 基于线程池

Thread和Runnabel区别:

(1)Runnable接口的实例是Thread的target,里面的run方法只是个方法体,而真正的线程对象依旧是Thread的实例,调用target的run方法。其实通过jdk文档可以明白很多,Thread类本身就已经实现了Runnable接口的,而通过实现Runnable接口创建的线程实际上是一个Runnable target作为Thread类的输入参数。new Thread(Runnable  target),这里的Thread对象的start方法为该线程创建执行初始化操作,然后调用了Runnable里的run方法。

(2)通过继承Thread类来创建的线程不共享实例变量,通过实现Runnable接口来创建的线程对象共享线程类的实例变量。如:例子中的变量i, 对于方法一输出的两个线程的 I 是不连续的 无关的;而方法二中的线程1和线程2,在i上的操作是连续的。 这是因为Runnable接口实现的只是Thread类的target,多个线程共享一个target,所以就共享其实例变量。

(3)Thread来创建线程类在调用当前线程的相关方法时可直接执行方法,而Runnable接口创建的线程类要通过Thread.currentThread()静态方法先获取当前线程,再调用其他方法。

(4)从Java8开始,Runnable接口使用了@FunctionalInterface修饰,支持函数式编程,Callabel接口也是支持函数式编程的。

(5)使用Thread类创建线程的局限就是不支持多继承,因为Java是单继承机制,所以为了多继承会通过实现Runnable接口来创建线程。

3.其他

start方法看起来执行了一个长期的方法调用,其实不是的,它很快就返回了,只是该方法调用的实际上是run方法的引用,并且这个方法还没执行结束呢,而这是另外一个线程执行的,所以run其实是和main同时运行,见下图。

Runnable导出一个类时,它的run只是一个方法而已,并不会有任何内在的线程能力,他必须显示的将任务附着在一个线程上。

多次调用start会出现IllegalThreadStateException异常;

start方法实际是将线程进入就绪状态,等待cpu执行run方法,如果直接调用thread.run方法,那么就和普通方法没差,不是异步操作,而是有main主线程调用一个方法而已。

 

/**   
* @Title: MyThread.java  
* @Package thread  
* @Description: TODO(用一句话描述该文件做什么)  
* @author LingLee 
* @date 2017年3月21日 下午2:47:33  
* @version V1.0   
*/   
package thread;

/**   
 * @Title: MyThread   
 * @Description:  
 */
class FirstThread extends Thread {
	
	private int i;//不共享实例变量
	public  void run(){
		for(;i<100;i++){
			System.out.println(getName()+"\t"+i);
		}
	}
}
class SecondThread implements Runnable{
	private int i;//共享实例变量
	public void run(){
		for(;i<100;i++){
			System.out.println(Thread.currentThread().getName()+"\t"+i);
		}
	}
}

public class MyThread {
	public static void main(String[] args){
		for(int i=0;i<50;i++ ){
			System.out.println(Thread.currentThread().getName()+"\t"+i);
			if(i==20){
//				new FirstThread().start();
//				new FirstThread().start();
				SecondThread st=new SecondThread();
				new Thread(st,"线程1").start();//真正的线程对象依然是Thread的实例,=
				new Thread(st,"线程2").start();//runnable只是thread类的target
			}
		}
	}

}

线程创建Thread和Runnable_第1张图片                             线程创建Thread和Runnable_第2张图片

 

4引申:一个类可以即继承Thread同时实现Runnable

例子

public class Test extends Thread implements Runnable{

	public static void main(String[] args){
		Thread t=new Thread(new Test());
		t.start();
	}
	/*
	Test没有实现Runnable中的run方法,是因为从Thread类中继承了run,这个run可以当做
	Runnable接口的实现。所以这段代码能够编译通过
	*/
}



public class Test extends Thread implements Runnable{


	public void run(){
		System.out.println("this is run");
	}
	public static void main(String[] args){
		Thread t=new Thread(new Test());
		t.start();
	}
	/*
	Test实现Runnable中的run方法,运行结果为this is run
	*/
}

 

 

 

 

 

你可能感兴趣的:(Java)