线程的实现方式有四种:
第一种是继承Thread类,第二种是实现Runnable接口;第三种是实现Callable接口;最后是通过线程池创建线程。
写一个类继承Thread类,重写run()方法,然后调用start()方法启动线程。
class SubThread extends Thread{
public SubThread(String name) {
super(name);
}
@Override
public void run() {
for(char c='A';c<='Z';c++) {
System.out.println(this.getName()+c);
}
}
}
public class Demo01 {
public static void main(String[] args) {
SubThread t1 = new SubThread("线程甲");
SubThread t2 = new SubThread("线程乙");
SubThread t3 = new SubThread("线程丙");
t1.start();
t2.start();
t3.start();
}
}
写 一个类实现Runnable接口,重写run()方法;用Runnable接口的实现类的对象作为参数去实例化一个Thread对象,调用start()方法启动线程。
abstract class A{
public abstract void p();
}
class B extends A implements Runnable{
@Override
public void p() {
System.out.println(Thread.currentThread().getName()+"执行");
}
@Override
public void run() {
p();
}
}
public class Demo02 {
public static void main(String[] args) {
//每个Runnable接口的实现类,封装了线程的执行逻辑
B b = new B();
Thread t1 = new Thread(b,"线程1");
Thread t2 = new Thread(b,"线程2");
Thread t3 = new Thread(b,"线程3");
t1.start();
t2.start();
t3.start();
}
}
实现Runnable接口避免了单继承的局限性,代码可以被多个线程共享。
实现Callable接口,重写call()方法实现一个线程。
public class Demo03 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//Callable接口实现类,不同数据范围的计算任务
SubThread1 subThread1 = new SubThread1(0, 200);
SubThread1 subThread2 = new SubThread1(201, 500);
SubThread1 subThread3 = new SubThread1(501, 1000);
//Callable --> FutureTask(Runnable接口的实现类)
FutureTask task1 = new FutureTask<>(subThread1);
FutureTask task2 = new FutureTask<>(subThread2);
FutureTask task3 = new FutureTask<>(subThread3);
Thread t1 = new Thread(task1,"线程1");
Thread t2 = new Thread(task2,"线程2");
Thread t3 = new Thread(task3,"线程3");
//线程启动,
//tack1.run() --> callable.call()--> 结果-->outcome
t1.start();
t2.start();
t3.start();
//线程执行的返回值
System.out.println(task1.get());
System.out.println(task2.get());
System.out.println(task3.get());
}
}
class SubThread1 implements Callable{
int begin,end;
public SubThread1(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;
}
return sum;
}
}
使用Callable可以在线程任务结束后,会提供一个返回值。在调用了FutureTask的get()方法获取结果时,当前线程就会阻塞,直至call()方法结束返回结果。
线程池可以自动创建也可以手动创建,自动创建体现在Executors工具类中,常见的可以创建
FixedThreadPool:线程数固定的线程池,使用Executors.newFixedThreadPool()创建;
CachedThreadPool:线程数根据任务动态调整的线程池,使用Executors.newCachedThreadPool()创建;
SingleThreadExecutor:仅提供一个单线程的线程池,使用Executors.newSingleThreadExecutor()创建;
ScheduledThreadPool:能实现定时、周期性任务的线程池,使用Executors.newScheduledThreadPool()创建;
public class Demo01 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(4);
List> futureList = new ArrayList<>();
for (int i = 0; i <= 900000; i+=100000) {
Future f = executorService.submit(new Leijia(i, i+100000));
futureList.add(f);
}
int result = 0;
for (int i = 0; i < futureList.size(); i++) {
result += futureList.get(i).get();
}
executorService.shutdown();
while(!executorService.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("还没有关闭");
}
System.out.println(result);
}
}
class Leijia implements Callable{
private int begin,end;
public Leijia(int begin,int end) {
this.begin = begin;
this.end = end;
}
@Override
public Integer call() throws Exception {
int result = 0;
for (int i = begin; i <= end; i++) {
result += i;
}
System.out.println(Thread.currentThread().getName()+"正在执行"+begin+"到"+end+"的累加");
return result;
}
}
线程池中的线程自从线程池创建就会处于运行状态。线程任务的执行从提交线程任务开始。submit()方法可以接收Runnable跟Callable接口的实现类对象。excute()方法只能接收Runnable接口的实现类对象。