创建多线程
方式一:继承Thread类
- 定义一个子类MyThread继承线程类java.lang.Thread,重写run方法
- 创建MyThread类的对象
- 调用线程对象的start()方法启动线程(启动后还是执行run方法)
优缺点:
- 优点:编码简单
- 确定:线程类已经继承Thread,无法继承其他类,不利于功能的扩展
多线程的注意事项:
- 启动线程必须调用start方法,不是调用run方法;
- 不要把主线程任务放在启动子线程之前
方式二:实现Runnable接口
- 定义一个线程任务类MyRunnable实现Runnable接口,重写run方法
- 创建MyRunnable任务对象
- 把MyRunnable任务对象交给Thread处理
- 调用线程对象的start()方法启动线程
优缺点: - 优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强
- 确定:需要多一个Runnable对象
另一种写法:匿名内部类写法
- 可以创建Runnable的匿名内部类对象
- 再交给Thread线程对象
- 再调用线程对象start启动线程
匿名内部类的简化方法
方式三:实现Callable接口
如果线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。
解决方法:
- JDK 5 提供了Callable接口和FutureTask类来实现(多线程的第三种创建方式)
- 最大优点:可以返回线程执行完毕后的结果
- 创建任务对象:
(定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据)
(把Callable类型的对象封装成FutureTask(线程任务对象)) - 把线程任务对象交给Thread对象
- 调用Thread对象的start方法启动线程
- 线程执行完毕后,通过FutureTask对象的get方法获取线程任务执行的结果
线程的常用API
为什么先输出的是线程的名字?
因为线程启动时就可以拿到该线程的名字,此时线程还没有来得及执行任务。
线程的名字有什么用?
名字用于区分线程,可以用Thread.currentThreae(),获取执行的线程对象(哪个线程执行它,它就会得到哪个线程对象)