线程的创建方式有四种:
方式一:继承java.lang.Thread类
创建一个类继承Thread类,然后重写Thread类中的run()方法
class SubThread extends Thread{
public SubThread(String name) {
super(name);
}
@Override
public void run() {
for( char c='A';c<'z';c++) {
System.out.printf("[%s]:%s\n",this.getName(),c);
}
super.run();
}
}
public class Demo02 {
public static void main(String[] args) {
SubThread t1=new SubThread("线程1");
SubThread t2=new SubThread("线程2");
SubThread t3=new SubThread("线程3");
t1.start();
t2.start();
t3.start();
}
}
方式二:实现Runnable接口
定义Runnable接口的实现类,重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行类,创建Runnable实现类的实例,并用这个实例作为Thread的参数来创建Thread对象。
class EmailTask extends Task implements Runnable{
@Override
public void execute() {
//获取当前线程对象对象
Thread currentThread=Thread.currentThread();
//获取线程名称
String name=currentThread.getName();
System.out.println(name+"发送邮件");
}
public void run() {
execute();
}
}
//父类任务
abstract class Task{
public abstract void execute();
}
public class Demo03 {
public static void main(String[] args) {
//每个runnnable接口的实现类封装了线程的实现逻辑
EmailTask emailTask=new EmailTask();
//创建3个线程分别发送邮件
Thread t1=new Thread(emailTask,"线程1");
Thread t2=new Thread(emailTask,"线程2");
Thread t3=new Thread(emailTask,"线程3");
//启动线程
t1.start();
t2.start();
t3.start();
}
方式三:实现Callable接口
(1)创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例
(2)使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
(3)使用FutureTask对象作为Thread对象的参数创建并启动线程(因为FutureTask实现了Runnable接口)
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
public class Demo04 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//Callable接口实现类:不同数据范围的计算任务
SumCaclTask task1=new SumCaclTask(0, 100);
SumCaclTask task2=new SumCaclTask(101,500);
SumCaclTask task3=new SumCaclTask(501,1000);
//Callable->FutureTask(Runnable的实现类)
FutureTask<Integer> futureTask1=new FutureTask<Integer>(task1);
FutureTask<Integer> futureTask2=new FutureTask<Integer>(task2);
FutureTask<Integer> futureTask3=new FutureTask<Integer>(task3);
//创建并启动线程
Thread t1=new Thread(futureTask1);
Thread t2=new Thread(futureTask2);
Thread t3=new Thread(futureTask3);
//线程启动 run() call()
t1.start();
t2.start();
t3.start();
//线程执行结束分别获取各自线程的执行结果
System.out.println("开始分别获取");
Integer sum1=futureTask1.get();
Integer sum2=futureTask2.get();
Integer sum3=futureTask3.get();
//汇总
System.out.println("汇总计算结果");
Integer result=sum1+sum2+sum3;
System.out.println("最终计算结果:"+result);
}
}
方式四:线程池
线程池是按照核心线程数、最大线程数等参数配置实现创建并管理线程的过程。
程序在需要使用线程时,将任务传给线程池,线程池选择一个空闲状态的线程执行任务,任务执行结束后,该线程又会处于空闲状态。
调用Exectors工具类的nreFixedThreadPool()方法
调用execute()执行任务
重写run()方法
ExecutorService executorService=Executors.newFixedThreadPool(5);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"进行了一次投票");
//休眠1秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}