当前位置:首页 > 天道酬勤 > 正文内容

java线程通信(java实现多线程)

张世龙2021年12月20日 07:36天道酬勤250

实现线程的方法到底有多少种? 大多数人说有两种、三种或四种,但很少有人说有一种。 让我们来看看具体指的是什么。

实现Runnable接口

publicclassrunnablethreadimplementsrunnable {

@Override

公共语音运行()

system.out.println (“实现runnable接口来实现线程”)

}

}2.继承thread类

publicclassextendsthreadextendsthread {

@Override

公共语音运行()

system.out.println (在thread类中实现线程);

}

}与第一种方法不同,没有实现接口,继承了Thread类,并重写了其中的run ()方法。

3 .线程池创建线程

staticclassdefaultthreadfactoryimplementsthreadfactory {

默认引用工厂

安全管理器=system.getsecuritymanager (;

组=(s () s!=空值? 获取网格组() :

Thread.currentThread () .获取阈值组);

名称前缀='保罗- '

使用poolNumber.getAndIncrement (

'-thread-';

}

publicthreadnewthread (运行r ) {

hreadt=new thread (组,r,

nameprefixthreadnumber.getandincrement (

0;

if (美国达蒙) )

t .设定域名(假);

获得优先级()!=thread.norm _优先级)

t .设置优先级(thread.norm _优先级;

返回t;

}

对于线程池,本质上是从线程工厂创建线程,缺省情况下采用DefaultThreadFactory。 线程池创建的线程具有缺省值,如线程名称、是否为守护程序和线程优先级。

但是,无论如何设置这些属性,最终都会从new Thread ()创建线程,但是这里的构造函数会传递很多参数。

由此可见,从线程池创建线程本质上是通过new Thread ()实现的,因此没有脱离前两种基本的创建方法。

面试点的回答:

在说明了前两种方法之后,他进一步说:“我知道线程池和Callable也可以创建线程,但本质上是通过前两种基本方法实现的线程创建。 ”。

4 .具有返回值的Callable创建线程

classcallabletaskimplementscallableinteger {

@Override

公共整合者呼叫() throws执行{ }。

返回新随机() .下一个);

}

}

//创建线程池

executorserviceservice=executors.newfixedthreadpool (10;

//通过Future提交任务并返回结果

futureintegerfuture=service.submit (newcallabletask (); 虽然Runnable创建的线程没有返回值,但是Callable及其关联的Future和FutureTask可以将线程执行的结果作为返回值返回,如代码所示。 实现Callable接口,将通用性设置为Integer,并返回随机数。

但是,无论是Callable还是FutureTask,首先都和Runnable一样是任务,应该执行,而不是执行

本身就是线程。

它们可以放到线程池中执行,如代码所示, submit() 方法把任务放到线程池中,并由线程池创建线程,不管用什么方法,最终都是靠线程来执行的,而子线程的创建方式仍脱离不了最开始讲的两种基本方式,也就是实现 Runnable 接口和继承 Thread 类。

5. 其他创建方式

class TimerThread extends Thread { //具体实现 }

定时器也可以实现线程,如果新建一个 Timer,令其每隔 10 秒或设置两个小时之后,执行一些任务,那么这时它确实也创建了线程并执行了任务。

但如果我们深入分析定时器的源码会发现,本质上它还是会有一个继承自 Thread 类的 TimerThread,所以定时器创建线程最后又绕回到最开始说的两种方式。

或许你还会说,我还知道一些其他方式,比如匿名内部类或 lambda 表达式方式。

/** *描述:匿名内部类创建线程 */ new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }).start(); } }

实际上,匿名内部类或 lambda 表达式创建线程,它们仅仅是在语法层面上实现了线程,并不能把它归结于实现多线程的方式,如匿名内部类实现线程的代码所示,它仅仅是用一个匿名内部类把需要传入的 Runnable 给实例出来。

new Thread(() -> System.out.println(Thread.currentThread().getName())).start(); }

再来看 lambda 表达式方式,最终它们依然符合最开始所说的那两种实现线程的方式。

到这里,我们先认为有两种创建线程的方式,而其他的创建方式,比如线程池或是定时器,它们仅仅是在 new Thread() 外做了一层封装,如果我们把这些都叫作一种新的方式,那么创建线程的方式便会千变万化、层出不穷,比如 JDK 更新了,它可能会多出几个类,会把 new Thread() 重新封装,表面上看又会是一种新的实现线程的方式,透过现象看本质,打开封装后,会发现它们最终都是基于 Runnable 接口或继承 Thread 类实现的。

-----------

本文整理自《Java并发编程78讲》技术专栏

勾哥:mgdxm说到现在,我们能理解所有实现线程的方式归根结底就是基于 Runnable 接口或继承 Thread 类,那为什么mgdxm一开始说这两种方式本质上是一种呢?

关注公号 勾勾的Java宇宙,下期告诉你。

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/25484.html

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。