方式一:继承于Thread类(共享数据要加static)
1.创建一个继承于Thread类的子类
2.重写Thread类的run() --> 将此线程执行的操作声明在run()中
3.创建Thread类的子类的对象
4.通过此对象调用start():①启动当前线程 ②调用当前线程的run()
问题一:我们不能用通过直接调用run()的方式启动线程
问题二:在启动一个线程,遍历100以内的偶数(例子中的线程里面的功能 ).不可以还让已经start()的线程去执行.会报IllegalThread
我们需要重新创建一个线程的对象
例如:
创建Thread类的匿名子类的方式
方式二:实现Runnable接口
1.创建一个实现了Runnable接口的类
2.实现类去实现Runnable中的抽象方法:run()
3.创建实现类的对象
4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
前两种方式的对比:开发中优先使用实现Runnable接口方式
1.实现的方式没有类的单继承性的局限性
2.实现的方式更适合来处理多个线程共享数据的情况
前两种方式的联系:
public class Thread implements Runnable
相同点:
两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
方式三:实现Callable接口(JDK5.0之后)
1.创建一个实现Callable的实现类
2.实现call方法,将此线程需要执行的操作声明在call()中
3.创建Callable接口实现类的对象
4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
5.讲FutureTask的独享作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
6.获取Callable中call方法的返回值
get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大
① call()可以有返回值
② call()可以抛出异常,被外面的操作捕获,获取异常的信息
③ Callable是支持泛型的
方式四:使用线程池
execute() 执行 shutdown() 关闭连接池
思路:提前创建好多个线程,放入线程池中,使用是直接取走,使用完放回池中.可以避免频繁创建销毁.实现重复利用.累似生活中的公共交通