1、继承Thread类的方式:
步骤1:创建一个继承于Thread类的子类
步骤2:重写Thread类的run() --> 将此线程执行的操作声明在run()中
步骤3:创建Thread类的子类的对象
步骤4:通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
2、实现Runnable接口的方式:
步骤1:创建一个实现了Runnable接口的类
步骤2:实现类去实现Runnable中的抽象方法:run()
步骤3: 创建实现类的对象
步骤4:将此对象作为参数传递到Thread类的构造器中(Thread(Runnable target)),创建Thread类的对象
步骤5:通过Thread类的对象调用start()
在上述两种方式中,优先选择是实现Runnable接口的方式,原因:
1、没有单继承的局限性
2、实现的方式更适合来处理多个线程共享数据的情况
3、JDK5.0新增方式:实现Callable接口
步骤1:创建一个实现Callable的实现类
步骤2:实现call方法,将此线程需要执行的操作声明在call()中
步骤3:建Callable接口实现类的对象 NewThread newThread = new NewThread();
步骤4:此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象 FutureTask futureTask = new FutureTask(newThread);
步骤5:将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start() new Thread(futureTask).start();
步骤6:获取Callable中call方法的返回值 Object sum = futureTask.get();
这种方式的优点:
call()可以返回值的。
call()可以抛出异常,被外面的操作捕获,获取异常的信息
Callable是支持泛型的
4、线程池
步骤1:提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
步骤2:执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
service.execute(new NumberThread());//适合适用于Runnable
service.execute(new NumberThread1());//适合适用于Runnable
步骤3:关闭连接池
service.shutdown();
线程池的好处:
提高响应速度(减少了创建新线程的时间)
降低资源消耗(重复利用线程池中线程,不需要每次都创建)
便于线程管理
corePoolSize:核心池的大小
maximumPoolSize:最大线程数
keepAliveTime:线程没任务时最多保持多长时间后会终止