我们在创建一个线程时,是通过创建Thread实例完成线程的创建,但在具体的实现方式上可以有4种方式。
线程创建方式1:继承Thread
我们可以通过继承Thread类去重写run()方法来创建一个线程。代码参考实现如下:
//继承Thread,重写run()方法
class myThread extends Thread{
public myThread(String name) {
super(name);
}
@Override
public void run() {
for(int i=0;i<100;i++) {
System.out.printf("[%s]=%d\n",this.getName(),i);
}
}
}
public static void main(String[] args) {
myThread t1=new myThread("线程A");//创建线程
t1.start();//启动线程
}
线程创建方式2:实现Runnable接口
我们可以通过实现Runnable接口来重写run()方法,创建一个线程。代码参考如下:
class MailTask extends Task implements Runnable{
@Override
public void excute() {
//获得当前线程对象
Thread t=Thread.currentThread();
System.out.println(t.getName()+"使用JavaMail技术发送邮件");
}
@Override
public void run() {
excute();
}
}
abstract class Task{
public abstract void excute();
}
public static void main(String[] args) {
//每个Runnable接口的实现类,封装了线程执行逻辑
MailTask mailTask=new MailTask();
//创建3个线程
Thread t1=new Thread(mailTask,"线程T1");
Thread t2=new Thread(mailTask,"线程T2");
Thread t3=new Thread(mailTask,"线程T3");
//启动线程
t1.start();
t2.start();
t3.start();
}
线程创建方式3:实现Callable接口
通过实现Callable接口重写它的call()方法也可以实现接口的创建,Callable和Runnable接口的区别在于Runnable的run()方法没有返回值,而Callable的call()方法有返回值,并且Callable的实现类需要通过FutureTask<T>来包装后使用Thread(Future)来创建线程。代码参考实现如下:
//线程创建方式3:实现Callable接口
class SumCalcTask implements Callable<Integer>{
private int begin,end;
public SumCalcTask(int begin,int end) {
this.begin=begin;
this.end=end;
}
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=begin;i<=end;i++) {
sum+=i;
}
System.out.println(Thread.currentThread().getName());
return sum;
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
//Callable接口实现类:不同数据范围的计算任务
SumCalcTask task1=new SumCalcTask(1, 300);
SumCalcTask task2=new SumCalcTask(301, 500);
SumCalcTask task3=new SumCalcTask(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);
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 total=sum1+sum2+sum3;
System.out.println("总和:"+total);
}
线程创建方式4:通过线程池创建
通过线程池,我们也可以创建出一个线程,线程池中的线程不需要我们自己启动,他会自己启动线程,但使用完后我们需要使用shutdown()方法关闭线程池。代码实现参考如下:
public static void main(String[] args) {
//固定数量(10)的线程池
ExecutorService executorService=Executors.newFixedThreadPool(10);
//不确定数量的线程请求
while(true) {
//向线程池提交一个执行任务(Runnable接口实现类对象)
//线程池分配一个“空闲线程”执行该任务
//如果没有空闲线程,则该任务进入“等待队列”(工作队列)
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"进行了一次投票!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}