1.用继承Thread类,重写它的run()方法。
我们可以从图中发现Thread类实现了Runnable接口并且重写了run()方法。而创建线程的第一种方式就是继承Thread类并重写它的run()方法。但是这样做就有缺点,你继承Thread类之后就不能继承其它的类了,不易后期的维护。
我就以计算1-100之内数之和为例:
public class TestThread {
public static void main(String[] args) {
new MyThread().start();
}
}
class MyThread extends Thread{
@Override
public void run() {
int sum=0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
System.out.println("sum="+sum);
}
}
2.实现Runnable接口,重写run()方法。
这个方法较之前的方法要好一点,但是也有缺点,就是run()方法不能有返回值和抛出异常。
public class TestRunnable {
public static void main(String[] args) {
new Thread(new MyRunnable()).start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
int sum=0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
System.out.println("sum="+sum);
}
}
3.实现Callable接口,重写call()方法。
相较于Runnable接口的方式,方法可以有返回值,并且可以抛出异常。但是此方式需要FutureTask类支持来获取run()方法的返回值。
从图中我们可以看到,FutureTask类实现了RunnableFuture接口,而RunnableFuture继承了Future接口和Runnable接口。
public class TCallable {
public static void main(String[] args) {
MyCallable callable = new MyCallable();
FutureTask<Integer> futureTask=new FutureTask<>(callable);
new Thread(futureTask).start();
try {
//需要注意的一点是,在得到结果之前,Future接口的get()方法会一直阻塞和ServerSocket类的accept()方法一样
int sum=futureTask.get();
System.out.println("sum="+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
return sum;
}
}
4.使用线程池的方式来创建线程。
1.线程池:提供了一个线程队列,队列中保存者所有等待状态的线程, 避免了创建与销毁额外开销,提高了相应速度。
二、线程池的体系结构:
java.util.concurrent.Executor:负责线程的使用与调度的共接口
|–**ExecutorService 子接口:线程池的主要接口
|–ThreadPoolExecutor 线程池的实现类
|–ScheduleExecutorService 子接口:负责线程的调度
|–ScheduleThreadPoolExecutor:继承ThreadPoolExecutor,
实现ScheduleExecutorService
三、工具类 :Executors
ExecutorService newFixedThreadPool():创建固定大小的线程池
ExecutorService newFixedThreadPool():缓存线程池,线程池的大小数量不固定,可以根据需求自动的更改数量
ExecutorService newSingleThreadExecutor():创建单个线程,线程池中只有一个出现线程
ScheduleExecutorService newScheduleThreadPool():创建固定大小的线程,可以延迟或定时的执行任务
public class TestThreadPool {
public static void main(String[] args) {
//1.创建线程池
ExecutorService pool = Executors.newFixedThreadPool(5);
MyThreadPool myThreadPool = new MyThreadPool();
//2.线程池中分配任务
Future<Integer> future = pool.submit(myThreadPool);
try {
int sum=future.get();
System.out.println("sum="+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
//3.关闭线程池
pool.shutdown();
}
}
}
class MyThreadPool implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
return sum;
}
}