在我们学习java基础的时候,我们会基础到线程这一章节,大多数刚刚接触的,都会被先了解到实现创建线程有2种方式,继承Thread类和实现Runnable接口; 但是经过后面我们会知道,实现多线程并非只有这两种方式,还有另外两种,那就是实现Callable接口和使用线程池; 那么这里实现多线程的方式就有4种了。
A)继承Thread类
package com.czy.fourThread;
public class Oneextends {
public static void main(String[] args) {
FirstThread t1=new FirstThread();
t1.start();
}
}
class FirstThread extends Thread{
@Override
public void run() {
// TODO 自动生成的方法存根
System.out.println("i am extends thread");
}
}
B)实现Runnable接口
package com.czy.fourThread;
public class Secondimplement {
public static void main(String[] args) {
SecondThread st=new SecondThread();
new Thread(st).start();
}
}
class SecondThread implements Runnable{
@Override
public void run() {
// TODO 自动生成的方法存根
System.out.println("i am implents Runnable thread");
}
}
在这里我们查看Thread的 源码
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
实际上Thread类也实现了Runnable接口,实现run()方法;
C)实现Callable接口
package com.czy.fourThread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreeImplements {
public static void main(String[] args) {
ThreeThread tt=new ThreeThread();
FutureTask<String> result=new FutureTask<>(tt);
new Thread(result).start();
try {
System.out.println("return value:"+result.get());
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ExecutionException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
class ThreeThread implements Callable<String>{
@Override
public String call() throws Exception {
// TODO 自动生成的方法存根
System.out.println("i am implements Callable thread");
return "yes";
}
}
这里的call方法就相当于是之前的run方法,不过callable和前两种的区别一目了然,就是需要借助FutureTask去启动线程,并且线程方法有返回值,也可以抛出异常;并且FutureTask启动方式是加了闭锁的;改造之前的代码:
package com.czy.fourThread;
public class Secondimplement {
public static void main(String[] args) throws InterruptedException {
SecondThread st=new SecondThread();
new Thread(st).start();
System.out.println("i am main---------");
}
}
class SecondThread implements Runnable{
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=0;i<10;i++)
System.out.println("i am implents Runnable thread");
}
}
运行结果:
i am main---------
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
i am implents Runnable thread
这里看到 main线程启动了子线程,然后继续运行,先做了main线程的输出操作
package com.czy.fourThread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreeImplements {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ThreeThread tt=new ThreeThread();
FutureTask<String> result=new FutureTask<>(tt);
new Thread(result).start();
System.out.println("return value:"+result.get());
}
}
class ThreeThread implements Callable<String>{
@Override
public String call() throws Exception {
// TODO 自动生成的方法存根
for(int i=0;i<10;i++)
System.out.println("i am implements Callable thread");
return "yes";
}
}
运行结果:
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
i am implements Callable thread
return value:yes
而在这里,我们的main线程没有继续执行,而是等待了我们的子线程的运行结束,才继续运行,这就是加了闭锁;
我们通过源码来观察下FutureTask类:
public class FutureTask<V> implements RunnableFuture<V> {
可以看到FutureTask实现了RunnableFuture接口,Runnable?! 是不是有点熟悉,在继续往下看
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
这不就是又回到了我们的Runnable接口了吗.......
D)线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Fourthpool {
public static void main(String[] args) {
Fourcase fourcase=new Fourcase();
ExecutorService executorService=Executors.newFixedThreadPool(5);
for(int i=0;i<10;i++){
executorService.submit(fourcase);
}
}
}
class Fourcase implements Runnable{
private int i;
@Override
public void run() {
// TODO 自动生成的方法存根
System.out.println(Thread.currentThread().getName()+":"+ ++i);
}
}
运行结果:
pool-1-thread-2:1
pool-1-thread-3:3
pool-1-thread-2:5
pool-1-thread-2:6
pool-1-thread-1:2
pool-1-thread-2:8
pool-1-thread-3:7
pool-1-thread-4:4
pool-1-thread-1:9
pool-1-thread-5:10
使用线程池的方法有多种,这里先写这一种