线程:(thread) 是一个程序内部一条执行路径
我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径
多线程的学习
1.多线程的创建(如何在程序中实现多线程,有哪些方式,搁置有什么优缺点)
2.Tread类的常用方法(线程的代表是Thread类,Thread)提供了那些线程的操作给我们呢?
3.线程安全、线程同步(多个线程同时访问一个共享的数据的时候会出现问题,如何去解决?)
4.线程通信、线程池(线程与线程键需要配合完成一些事情。线程池是一种线程优化方案,可以用一种更好的方式使用多线程)
5.定时器、线程状态等(如何在程序中实现定时器?线程在执行的过程中会有很多不同的状态,理解这些状态有助于理解线程的执行原理,也有利于面试)
多线程的创建
1.方式一:继承Thread类
2.方法二:实现runnable接口
3.方法三:JDK5.0新增:实现callable接口
多线程的实现方案一:继承Thread类
1.定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法
2.创建MyThread类的对象
3.调用线程对象的start()方法启动线程(启动后还是执行run方法的)
方法一优缺点:
优点:编码简单
缺点:线程类已经继承Thread,无法继承其他类,不利于扩展
(注意:不能直接调用run方法,而是调用start启动线程,run相当于普通方法执行
相当于单线程执行
若主线程任务放在子线程之前,主线程一直是先跑完,相当于是一个单线程的效果了)
方法一总结(继承Tread类、重写run方法、创建线程对象、调用start()方法启动)
package study;
//目标:多线程的创建方式一:继承thread类实现
//1.定义一个线程类继承thread类
//2.重写run方法,里面是定义线程以后要干啥
public class Threaddome1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//2.new一个新线程对象
Thread t=new MyThread();
//4.调用start方法启动线程(执行的还是run方法)
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行输入"+i);
}
}
}
class MyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
System.err.println("子线程执行输出:"+i);
}
}
}
多线程的实现方案二:实现Runnable接口
1.定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法
2.创建MyRunnable任务对象
3.把MyRunnable任务交给Thread处理
4.调用线程对象的start()方法启动线程
Thread的构造器
构造器 说明
public Thread(String name) 可以为当前线程制定名称
public Thread(Runnable target) 封装Runnable对象成为线程对象
public Thread(Runnable target , String name) 封装Runnable对象成为线程对象,并指定线程名称
方法二优缺点
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强
缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的
package study;
public class Treaddemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//3.创建一个任务对象
Runnable target=new MyRunable();
//4.把任务对象交给Thread处理
Thread t = new Thread (target);
//5.启动线程
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程执行输出:"+i);
}
}
}
//1.定义一线程任务类实现Runnable接口
class MyRunable implements Runnable{
//2.重写run方法
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程执行输出"+i);
}
}
}
1.前2种线程创建方式都存在一个问题:
他们重写的run方法均不能直接返回结果
不适合需要返回线程结果的业务场景
多线程的实现方案三:利用Callable、FutureTask接口实现
1.得到任务对象
2.定义类实现Callable接口,重写call方法,封装要做的事情
2.把线程任务对象交给Thread处理
3调用Thread的start方法启动线程,执行任务
线程执行完毕后、通过FutureTask的get方法去获取任务执行的结果
方法名称 说明
public FutureTask<>(Callable call) 把Callable对象封装成FutureTask对象
public V get() threws Exception 获取线程执行call方法返回的结果
方法三优缺点
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强
可以在线程执行完毕后去获取线程执行的结果
缺点:编码复杂
总结
方法 优点 缺点
继承Thread类 编程比较简单,可以直接使用Thread类中的方法 扩展性较差,不能再继承其他 的类,不能返回线程执行的结 果
实现Runnable 接口 扩展性强,实现该接口的同时还可以 编程相对复杂,不能返回线程
继承其他的类。 执行的结果
实现Callable接口 扩展性强,实现该接口的同时可以 编程相对复杂
继承其他的类。可以得到线程执行的结果