JavaSE学习——创建线程的三种方式

JavaSE学习——创建线程的三种方式

通过继承Thread类创建

以继承Thread方式创建,不能再实现其他父类的扩展

通过实现Runnable接口创建

以实现Runnable方式创建,可以继续实现其它接口或单继承其它类线程实例和任务实例都是独立的实例,降低了耦合度

通过Callable和Future创建

以实现Callable接口方式创建,可以继续实现其它接口或单继承其它类能够不用自己处理异常(可抛出),具有返回值

1.通过继承Thread类创建

(1) 定义Thread类的子类并覆写该类的run()方法

//音乐线程
class Music extends Thread{
	@Override
	public void run(){
		for(int i = 0; i < 50; i++){
			System.out.println("listening music" + i + "time");
		}
	}
}
//游戏线程
class Game extends Thread{
	@Override
	public void run(){
		for(int i = 0; i < 50; i++){
			System.out.println("play game" + i + "time");
		}
	}
}

这里创建了两个Thread的子类用来表现两个演示多线程的运行

(2) 创建Thread子类的实例

public class MyThread{
	public static void main(String[] args){
		Music music = new Music();//创建music子类实例
		Game game = new Game();//创建game子类实例

(3)调用线程对象的start()方法启动线程

		music.start();//启动音乐线程
		game.start();//启动游戏线程
	}
}

在运行结果中可以看到两个线程的交叉执行

2.通过实现Runnable接口创建

(1) 定义Runnable接口的实现类,并覆写该接口的run()方法

class Music implements Runable{

	@Override
	public void run(){
		for(int i = 0; i < 50; i++){
			System.out.println("listening music" + i + "time");
		}
	}
}

class Game implements Runable{

	@Override
	public void run(){
		for(int i = 0; i < 50; i++){
			System.out.println("play geme" + i + "time");
		}
	}
}

(2) 创建Runnable实现类的实例,并以此实例作为Thread的参数来创建Thread线程对象

public class MyThead{
	public static void main(String[] args){
		Music music = new Music();//创建Runnable实现类的实例music
		Game game = new Game();//创建Runnable实现类的实例geme
		
		Thread t1 = new Thread(music);//创建线程对象t1
		Thread t2 = new Thread(game);//创建线程对象t2

(3) 调用线程对象的start()方法启动线程

		t1.start();//启动线程t1
		t2.start();//启动线程t2
	}
}

3.通过Callable和Future创建

(1) 创建Callable接口的实现类,并实现call()方法该方法将作为线程执行体,并且有返回值)

class MyCallable implements Callable<Integer>{//此处以Integer为例

	@Override
	public Integer call() throws Exception {//覆写call()方法
	//call()方法内用来写想要在线程里执行的代码
		for (int i = 0; i < 100; i++) {
			System.out.println("MyCallable" + i +"time");
		}
		return 36;//这种创建线程的方式可以有返回值,并且可以抛出异常
	}
	
} 

(2) 创建Callable实现类的实例,使用FutureTask类来创建Callable对象
(该FutureTask对象封装了该Callable对象的call方法的返回值)

package cn.itsoure._09Callable_Future;

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

public class Callable_Future {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//创建一个线程
		ExecutorService ser = Executors.newFixedThreadPool(1);
		//将实现了Callable接口的类实例化
		MyCallable myCallable = new MyCallable();

(3) 使用FutureTask对象作为Thread对象的target创建并启动新线程

		//submit(Runnable task) 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
		//将实现了Callable接口的实例化加入线程
		Future<Integer> resule = ser.submit(myCallable);
		//ser.submit(myCallable);//不需要返回值可以直接使用submit

(4) 调用FutureTask对象的get方法来获取子线程执行结束后的返回值

		//get() 如有必要,等待计算完成,然后获取其结果。
		int num = resule.get();
		ser.shutdown();//关闭线程资源
		System.out.println(num);//打印返回的结果

相比于前两种创建线程的方式,第三种可以具有返回值,也可以抛出异常,但是相对代码更繁琐

猜你喜欢

转载自blog.csdn.net/qq_37937144/article/details/86573259