1.线程的创建
(1)线程的创建方式一:继承Thread类
/* * 1.定义一个任务类,实现Runnable接口 */ public class MyThread extends Thread{ // 重写runnable的run方法 @Override public void run() { for (int i = 0; i <=10 ; i++) { System.out.println("MyThread线程输出"+i); } } }
public class ThreadTest1 { // main方法是由一条默认的主线程负责执行 public static void main(String[] args) { // 3.创建MyThread线程类的对象代表一个线程 Thread t=new MyThread(); // 4.启动线程(自动执行run方法的) t.start();// main线程 t线程 for (int i = 0; i <=10 ; i++) { System.out.println("主线程main输出"+i); } } }
(2)线程的创建方式二:实现Runnable接口
1.定义一个多线程任务类MyRunnable实现Runnable接口,重写run()方法
2.创建一个Runnable任务对象
3.把MyRunnable任务对象交给Thread处理
public class MyRunnable implements Runnable{ @Override public void run() { for (int i = 0; i <=5 ; i++) { System.out.println("子线程输出"+i); } } }
public class ThreadTest2 { public static void main(String[] args) { // 3.创建任务对象 Runnable target=new MyRunnable(); // 4.把任务对象交给一个线程对象处理 new Thread(target).start(); for (int i = 0; i <=10 ; i++) { System.out.println("主线程main输出"+i); } } }
(3)线程的创建方式三:利用Callable接口,FutureTask类来实现
1.创建任务对象 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据 把Callable类型的对象封装成FutureTask(线程任务对象)
2.把线程任务对象交给Thread对象
3.调用Thread对象的start方法启动线程
4.线程执行完毕后,通过FutureTask对象的get方法去获取线程任务执行的结果
import java.util.concurrent.Callable; public class MyCallable implements Callable<String> { private int n; public MyCallable(int n) { this.n = n; } @Override public String call() throws Exception { // 描述线程的任务 // 需求: 求1-n的和 int sum=0; for (int i = 1; i <=n ; i++) { sum+=i; } return "线程求出了1-"+n+"的和是"+sum; } }
public class ThreadTest3 { public static void main(String[] args) throws ExecutionException, InterruptedException { // 3.创建一个Callable的对象 Callable <String> call=new MyCallable(100); // 4.把Callable的对象封装成一个FutureTask对象(任务对象) // 未来任务对象的作用? // 1.是一个任务对象,实现了Runnable对象 // 2.可以在线程执行完毕后,用未来任务对象调用get方法获取线程执行完毕后的结果 FutureTask <String> f1=new FutureTask<>(call); // 5. 把任务对象交给一个Thread对象 new Thread(f1).start(); // 6.获取线程执行完毕后返回的结果 String rs= f1.get(); System.out.println(rs); } }
2.三种创建线程的优缺点:
1.继承Thread类
优点:代码简洁
缺点:由于是单继承,已经继承了Thread类,就无法继承其他类,拓展性差,功能不足;重写的run方法不能直接返回结果
2.实现Runnable接口
优点:可以实现其它接口,和继承父类,拓展性强
缺点:重写的run方法不能直接返回结果
3.利用Callable接口,FutureTask类来实现
优点:可以返回结果,拓展性强
缺点:代码较繁琐