,,Java线程间的通信方式详解

,,Java线程间的通信方式详解

本文主要详细介绍Java线程间的通信,并结合代码和文本讨论线程间的通信。感兴趣的朋友可以参考一下。

本文总结了我对JAVA多线程中线程间通信的理解,主要通过代码和文本相结合的方式来讨论线程间的通信。因此,摘录了书中的一些示例代码,具体内容如下

同步

这里的同步意味着多个线程通过synchronized关键字相互通信。

参考示例:

公共类MyObject {

同步的公共void方法A() {

//做点什么.

}

同步的公共void方法B() {

//做一些其他的事情

}

}

公共类ThreadA扩展Thread {

私有MyObject对象;

//省略构造方法

@覆盖

公共无效运行(){

super . run();

object . methoda();

}

}

公共类ThreadB扩展Thread {

私有MyObject对象;

//省略构造方法

@覆盖

公共无效运行(){

super . run();

object . methodb();

}

}

公共类运行{

公共静态void main(String[] args) {

my object object=new my object();

//线程A和线程B持有相同的对象:object

ThreadA a=new ThreadA(object);

ThreadB b=new ThreadB(object);

a . start();

b . start();

}

}

因为线程A和线程B持有同一个MyObject类的object对象,虽然这两个线程需要调用不同的方法,但是它们是同步执行的。例如,线程B需要等待线程A执行完methodA()方法,然后才能执行methodB()方法。这样线程A和线程B就实现了通信。

这种方式,本质上就是“共享记忆”交流。多个线程需要访问同一个共享变量,谁得到锁(访问权)谁就可以执行。

while轮询的方式

代码如下:

导入Java . util . ArrayList;

导入Java . util . list;

公共类MyList {

private ListString list=new ArrayList string();

公共void add() {

list . add(“elements”);

}

public int size() {

返回list . size();

}

}

导入我的列表。MyList

公共类ThreadA扩展Thread {

私人MyList列表;

公共线程a(我的列表){

super();

this.list=list

}

@覆盖

公共无效运行(){

尝试{

for(int I=0;i 10i ) {

list . add();

system . out . println(' added '(I 1)' elements));

thread . sleep(1000);

}

} catch (InterruptedException e) {

e . printstacktrace();

}

}

}

导入我的列表。MyList

公共类ThreadB扩展Thread {

私人MyList列表;

公共线程b(我的列表){

super();

this.list=list

}

@覆盖

公共无效运行(){

尝试{

while (true) {

if (list.size()==5) {

System.out.println('==5,线程B准备退出');

抛出new interrupted exception();

}

}

} catch (InterruptedException e) {

e . printstacktrace();

}

}

}

导入我的列表。MyList

导入extthread。ThreadA

导入extthread。ThreadB

公共类测试{

公共静态void main(String[] args) {

my list service=new my list();

ThreadA a=new ThreadA(服务);

A . setname(“A”);

a . start();

ThreadB b=new ThreadB(服务);

B . set name(' B ');

b . start();

}

}

这样,线程A不断改变条件,线程ThreadB通过while语句不断检查这个条件(list.size()==5)是否为真,从而实现线程间的通信。但是这种方式会浪费CPU资源。之所以浪费资源,是因为JVM调度器把CPU交给线程B执行的时候,并没有做任何“有用”的工作,而是在不断测试某个条件是否成立。就像现实生活中,有人一直看着手机屏幕,看有没有来电,而不是:做别的。有电话时,按铃通知TA电话来了。关于线程轮询的影响,请参考:Java中一个线程执行无限循环的后果是什么?

wait/notify机制

代码如下:

导入Java . util . ArrayList;

导入Java . util . list;

公共类MyList {

private static ListString list=new ArrayList string();

公共静态void add() {

列表。add(“任何字符串”);

}

public static int size() {

返回列表。size();

}

}

公共类ThreadA扩展线程{

私有对象锁;

公共线程一个(对象锁){

super();

this.lock=lock

}

@覆盖

公共无效运行(){

尝试{

同步(锁定){

if (MyList.size()!=5) {

System.out.println('等待开始'

系统。当前时间毫秒());

锁定。wait();

System.out.println('等待结束'

系统。当前时间毫秒());

}

}

} catch (InterruptedException e) {

e。printstacktrace();

}

}

}

公共类ThreadB扩展线程{

私有对象锁;

公共线程乙(对象锁){

super();

this.lock=lock

}

@覆盖

公共无效运行(){

尝试{

同步(锁定){

for(int I=0;i 10i ) {

我的名单。add();

if (MyList.size()==5) {

锁定。notify();

System.out.println('已经发出了通知');

}

System.out.println('添加了我1 '个元素!');

线程。睡眠(1000);

}

}

} catch (InterruptedException e) {

e。printstacktrace();

}

}

}

公共类运行{

公共静态void main(String[] args) {

尝试{

对象锁=新对象();

ThreadA a=new ThreadA(lock);

答。start();

线程。睡眠(50);

ThreadB b=new ThreadB(lock);

乙。start();

} catch (InterruptedException e) {

e。printstacktrace();

}

}

}

线程A要等待某个条件满足时(list.size()==5),才执行操作。线程B则向目录中添加元素,改变目录的尺寸。

甲,乙之间如何通信的呢?也就是说,线程A如何知道list.size()已经为5了呢?

这里用到了目标类的等待()和通知()方法。

当条件未满足时(list.size()!=5),线程A调用等待()放弃CPU,并进入阻塞状态。 - 不像当轮询那样占用中央处理器

当条件满足时,线程B调用通知()通知线程一,所谓通知线程一,就是唤醒线程一,并让它进入可运行状态。

这种方式的一个好处就是中央处理器的利用率提高了。

但是也有一些缺点:比如,线程B先执行,一下子添加了5个元素并调用了通知()发送了通知,而此时线程A还执行;当线程A执行并调用等待()时,那它永远就不可能被唤醒了。因为,线程B已经发了通知了,以后不再发通知了。这说明:通知过早,会打乱程序的执行逻辑。

以上就是本文的全部内容,希望对大家学习Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)程序设计有所帮助。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: