实现线程方式只有一种

为什么说本质上实现线程只有一种方式?

实现Runnable 接口

public class RunnableThread implements Runnable {

    @Override
    public void run() {
        System.out.println("implents Runnable ...");
    }

    public static void main(String[] args) {
        new Thread(new RunnableThread()).start();
    }
}

第一种方式是通过实现Runnable接口实现多线程,如图所示,通过实现Runnable接口重写run方法,之后通过该对象创建Thread类实现多线程。

继承Thread类

public class ExtendsThread extends Thread {
    @Override
    public void run() {
        System.out.println("extends Thread ...");
    }

    public static void main(String[] args) {
        new ExtendsThread().start();
    }
}

第二种方式是通过继承Thread类,后重写run方法实现多线程。

线程池创建线程

public class ThreadPoolThread {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 50, TimeUnit.SECONDS, 
        	new PriorityBlockingQueue<>(), Executors.defaultThreadFactory());
        executor.submit(() -> {
            System.out.println("threadPool ...");
        });
    }
}

可以看到,如果我们创建线程池时不指定线程工厂时,默认使用DeafultThreadFactory工厂类来为线程池创建线程。那我们再看下DeafultThreadFactory类是如何创建线程的。

static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

从上面这段代码可以看出,DeafultThreadFactory创建线程是通过new Thread()方式创建的,并且会给线程设置名称、是否守护线程、线程优先级等等,因此本质上还是通过new Thread()方式创建的。

通过有返回值的Callable创建线程

public class CallableTask implements Callable<String> {

    @Override
    public String call() throws Exception {
        return "Implements Callable ...";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Future<String> future = Executors.newScheduledThreadPool(10).submit(new CallableTask());
        System.out.println(future.get());
    }
}

第四种线程创建方式是通过有返回值的Callable创建线程,Runnable创建线程是无返回值的,而Callable和与之相关的Future、FutureTask,它们可以把线程的执行结果作为返回值返回。
但是无论是Callable还是FutureTask,它们首先需要被执行的,而不是说它们本身就是线程,submit()方法把任务放到线程池中,并由线程池创建线程。因此本质上还是通过继承Thread或实现Runnable的方式实现线程的。

其他创建方式

定时器Timer

实现线程的方式只有一种

从上面的案例中我们可以看到,无论是通过线程池、或是定时器Timer,亦或是Callable,本质上都是对new Thread()做了一层包装。但是无论是继承Thread或是实现Runnable接口,这两种方式本质上是一种

public class Thread implements Runnable {
	private Runnable target;
	
	@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
}

启动线程需要调用start()方法,而start()方法最终还是调用run()方法,而从上面代码块可以看出,当我们通过Runnable方式创建Thread,最后执行的还是target.run()方法,而target对象就是当前传进来的Runnable实现类。而继承Thread类会直接重写run方法。因此我们可以看出,实现一个线程的方式就是构建一个Thread类 new Thread()。(可以这样理解,不论是继承Thread类,还是实现Runnable接口,最终的目的都是为了new Thread())。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值