线程的实现方式总结

线程的实现方式共有四种,第一种是继承Thread抽象类;第二种是实现Runnable接口;第三种是实现Callable接口;最后一种是通过线程池创建线程。

1.继承Thread类

写一个类去继承Thread类,重写其中的run()方法,然后调用start()方法启动线程。

2.实现Runnable接口

写一个类去实现Runnable接口,重写其中的run()方法;用用实现Runnable接口的对象作为参数实例化一个Thread对象,调用Thread类的start()方法来启动线程。

实现Runnable接口比继承Thread类所具有的优势:

1. 适合多个相同的程序代码的线程去共享同一个资源。 2. 可以避免java中的单继承的局限性。 3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。 4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

注意:

Thread类本质上也是实现了Runnable接口,启动线程的唯一方法就是通过Thread类的start()方法,run方法只是一个方法体。

start()方法是一个native(本地)方法,它将启动一个新线程,并执行run()方法(Thread类中提供的run()方法是一个空方法)。

然后我们再看看多线程的执行问题。

由图可以看出,输出的值是交替的无顺序的,原因分析:

调用start()方法后并不是立即执行多线程代码,而是使得该线程变为可运行状态,什么时候调度运行由操作系统决定的。

 

3.实现Callable接口


实现Callable接口,重写call()方法来实现一个线程。

Callable接口与Runnable接口的功能类似,但提供了比Runnable更强大的功能,主要表现为以下三点:

(1)Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能;

(2)Callable接口中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常,必须在run()捕获;

(3)运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,当调用Future的get方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果。

 

4.通过线程池创建线程

线程池可以自动创建也可以手动创建,自动创建体现在Executors工具类中,常见的可以创建newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool;手动创建体现在可以灵活设置线程池的各个参数,体现在代码中即ThreadPoolExecutor类构造器上各个实参的不同:

public static ExecutorService newFixedThreadPool(int var0) {
        return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
  }
	
public static ExecutorService newSingleThreadExecutor() {
        return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, 
        TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
  }
 
  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
  }
 
  public static ScheduledExecutorService newScheduledThreadPool(int var0) {
        return new ScheduledThreadPoolExecutor(var0);
 }

public ThreadPoolExecutor(int corePoolSize,
                           int maximumPoolSize,
                           long keepAliveTime,
                           TimeUnit unit,
                           BlockingQueue<Runnable> workQueue,
                           ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {……}

总结:

前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果

后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中

 

 

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中有多种实现线程方式。其中一种方式是使用线程池(ThreadPool)。线程池是一组预先创建的线程,可以重复使用来执行多个任务。通过使用ThreadPool.QueueUserWorkItem方法,可以将工作项加入到线程池队列中,并传递一个线程参数。这样,线程池会自动分配一个线程来执行该工作项。\[1\] 另一种方式是使用委托来开启多线程。通过定义一个委托,可以将需要在新线程中执行的方法传递给该委托,并使用Thread类的Start方法来启动新线程。在方法执行完毕后,可以使用回调函数来处理结果。\[2\] 还有一种方式是使用async/await关键字来实现异步、非阻塞的多线程。通过定义一个返回类型为Task的方法,并在方法内部使用await关键字来等待异步操作完成。这样可以在调用该方法时,不会阻塞主线程,并且可以获取到计算结果。\[3\] 总结起来,C#中实现线程方式包括使用线程池、使用委托和回调函数、以及使用async/await关键字。这些方式可以根据具体的需求和场景选择使用。 #### 引用[.reference_title] - *1* [C#多线程编程实现方式](https://blog.csdn.net/qq_33986919/article/details/79696505)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C# 中的多线程实现方式](https://blog.csdn.net/Upgrader/article/details/107774139)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值