一、线程的创建方式
线程有四种创建方式,下面就来介绍一下这四种实现方式
二、实现方式
1.继承的方式:继承Thread类,重写run方法,但是启动线程时不是调用run方法,而是调用父类的start方法
class ThreadDemo1 extends Thread{
@Override
public void run(){
System.out.println("线程的第一种创建方式");
}
}
//main方法调用
ThreadDemo1 demo1 = new ThreadDemo1();
demo1.start();
2.实现Runnable接口:
class ThreadDemo2 implements Runnable{
@Override
public void run() {
System.out.println("线程的第二种创建方式-实现runnable接口");
}
}
//main方法调用
ThreadDemo2 demo2 = new ThreadDemo2();
new Thread(demo2).start();
3.实现Callable接口:这个需要注意的是此接口是带泛型的,同时有返回值、抛异常的方式
class ThreadDemo3 implements Callable<Integer>{
private int i =0;
@Override
public Integer call() throws Exception {
for(int i=0;i<100;i++){
this.i+=i;
}
return i;
}
}
//main调用
ThreadDemo3 demo3 = new ThreadDemo3();
FutureTask<Integer> task = new FutureTask<>(demo3);
new Thread(task).start();
try {
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
}
简单跟踪一下这种创建方式:这个仔细看一下代码注释即可
//1.callable接口没什么特殊的
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
//2.重点来了,主要是FutrueTask接口,实现了RunnableFuture
public class FutureTask<V> implements RunnableFuture<V>;
private Callable<V> callable;//线程执行中需要做的事情,也就是说把线程run方法中需要运行的事情拿到外面来实现
private Object outcome;//返回线程最终执行结果
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
//3.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();
}
//4.可以看出FutureTask最终间接的实现了Runnable接口,那么必然有run方法了,callable中的call方法就是在run方法中执行的
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();//重点
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
//5.把run方法中调用call方法的计算结果传递出去
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
//6.获取执行结果
public V get() throws InterruptedException, ExecutionException {
int s = state;//这个属性是判断某种状态,没注意看
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
//7.最终返回结果
@SuppressWarnings("unchecked")
private V report(int s) throws ExecutionException {
Object x = outcome;//之前调用run方法时为此属性赋值的结果
if (s == NORMAL)
return (V)x; //计算结果
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
4.线程池的实现方式:
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 15, 200, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(5));
for(int i = 0;i<10;i++){
Runnable run = new Runnable(){
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
};
executor.execute(run);
System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
}
executor.shutdown();
}
从执行结果可以看出,当线程池中线程的数目大于5时,便将任务放入任务缓存队列里面,当任务缓存队列满了之后,便创建新的线程。如果上面程序中,将for循环中改成执行20个任务,就会抛出任务拒绝异常了。
不过在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors类中提供的几个静态方法来创建线程池:
Executors.newCachedThreadPool(); //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
Executors.newSingleThreadExecutor(); //创建容量为1的缓冲池
Executors.newFixedThreadPool(int); //创建固定容量大小的缓冲池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
使用工具类来创建线程池
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建固定大小的线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 5; i++) {
Future<Integer> result = pool.schedule(new Callable<Integer>(){
@Override
public Integer call() throws Exception {
int num = new Random().nextInt(100);//生成随机数
System.out.println(Thread.currentThread().getName() + " : " + num);
return num;
}
}, 1, TimeUnit.SECONDS);
System.out.println(result.get());
}
pool.shutdown();
}
}
线程池详细讲解请看:https://www.cnblogs.com/dolphin0520/p/3932921.html