目录
梗概
创建线程有4种方式,分别是继承Thread类重写run()方法、实现Runnable接口、实现Callable接口、线程池。但其实归根结底都是一种方式,就是new一个Thread对象。在后续案例中,可以看到这几种方式在创建线程调用方法到底层都创建了一个Thread对象。
注意
在此时创建出来的仅是一个线程对象,如果需要该线程执行线程任务,还需要执行start()方法启动线程,start()方法会调用run()执行操作,但不能直接使用run()方法来代替start()方法。这是由于在执行start()方法时,才真正的创建出一个线程并执行run()方法中的任务。如果只调用run()方法,线程并没有被创建,只是执行了一个方法而已。
1.继承自Thread类
重写Thread类的run()方法,该方法中定义了线程要执行的具体操作
Thread t1=new Thread(new MyThread(),"线程名");
t1.start();
//继承自Thread类的子类MyThread1
class MyThread1 extends Thread{
@Override
public void run(){
System.out.println("基于继承Thread类的线程创建方式");
}
}
实现了Runnable接口的Thread类
2.实现Runnable接口
对于Runnable接口中的run()方法,用于执行线程任务,无返回值
Thread t2=new Thread(new MyThread2(),"线程名");
t2.start();
//实现Runnable接口的子类MyThread2
class MyThread2 implements Runnable{
@Override
public void run(){
System.out.println("实现了Runnable接口的线程创建方式");
}
}
3.实现Callable接口
Callable接口中的call方法用于执行线程任务,有返回值。需要使用FutureTask对象接收返回值,该对象的类型是泛型,因此在创建时需要确定好类型。
FutureTask<String> f3=new FutureTask<String>(new MyThread12());
Thread t3=new Thread(f3,"线程名");
t3.start();
System.out.println(f3.get())
class MyThread3 implements Callable{
@Override
public Object call(){
return "基于Callable接口的创建线程的方式";
}
}
Callable接口是一个独立的接口,因此在创建线程对象时,需要先将该接口引用转换为FutureTask对象,该类间接实现了Runnable接口,
4.线程池
使用线程池创建对象需要使用newFixedThreadPool(参数)方法,其中参数的含义是需要该线程池创建几个线程对象。
线程池对象创建后,对于任务的执行需要调用execute()方法或submit()方法,前者接收一个Runnable对象,后者接收Callable对象。
另外,线程任务在执行结束后,该线程释放,回到线程池中,后续可以继续使用,线程池不会自动关闭,在程序执行结束后可以通过shutdown()方法或shutDownNow()手动关闭。
//线程池创建线程对象
ExecutorService executeService=Executors.newFixedThreadPool(1);
//execute:执行线程任务
executeService.execute(new Runnable(){
@Override
public void run(){
System.out.println("基于线程池创建的线程任务");
}
});
executeService.shutdown();