线程的四种创建方式

一、线程的创建方式

线程有四种创建方式,下面就来介绍一下这四种实现方式

二、实现方式

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值