1.继承于Thread类
1)创建一个继承于Thread类的子类
2)重写Thread类的run() --->将此线程执行的操作声明在run()中
3)创建Thread类的子类的对象
4)通过此对象调用start()
public class ThreadTest1{
public static void main(String[] args){
Thread1 test1 = new Thread1();
Thread1 test2 = new Thread1();
test1.start();
test2.start();
}
}
class Thread1 extends Thread{
//遍历100以内的整数
@Override
public void run(){
for(int i = 0; i < 100; i++){
//调用getName()方法显示当前线程名,方便观察
System.out.println(Thread.currentThread().getName() + ":" + i)
}
}
}
2.实现Runnable接口
1.创建一个实现Runnable接口 的类
2.实现类去实现Runable中的抽象方法:run()
3.实现实现类的对象
4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
public class ThreadTest2{
public static void main(String[] args){
Thread2 thread2 = neww Thread2();
Thresd test1 = new Thread(thread2);
Thread test2 = new Thread(thread2);
test1.start();
test2.start();
}
}
class Thread2 implements Runnable{
@Override
public void run(){
for (int i = 0; i<100;i++){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
3.实现Callable接口
1.创建一个实现Callable的实现类
2.实现call方法,将此线程需要执行的操作声明在call()中
3.创建Callable接口实现类的对象
4.将此Callable的接口实现类的对象作为参数传递到FutureTask的构造器中,创建FutureTask的对象
5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
6.获取Callable中call方法的返回值
如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
1).call()可以有返回值。
2).call()可以抛出异常,被外面的操作捕获,从而获取异常的信息
3).Callable是支持泛型的
4.使用线程池
提前创建好多个线程放入线程中,使用时直接获取,使用完放回池中。
1)提高了响应速度(减少创建新线程的时间)
2)降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
3)便于线程管理
1)corePoolSize:核心池的大小
2)maximumPoolSize:最大线程数
3)keepAliveTime:线程没有任务时最多保持多长时间会中止
ExecutorServiice:真正的线程池接口。
Executors:工具类,线程池的工厂类,用于创建并返回不同类型的线程池
5)比较前三种方式
1)实现的方式没有类的单继承性的局限性
2.实现的方式更适合处理多个线程有共享数据的情况。用据称则需要将数据static
相同点
两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
方式一的问题在于,需要让当前 类继承于Thread类,而java又是一个单继承的,这样的话为了创建多线程就会导致无法继承其他的类了