首页 > 编程知识 正文

java多线程通信方式,java线程之间如何通信

时间:2023-05-06 03:26:47 阅读:59162 作者:701

Java线程间通信

下一节

上述例题导致另一个线程无条件地阻止对一个方法的异步访问。 隐式管理进程在Java对象中的应用功能很强,但通过进程间通信可以到达更微妙的区域。 这在Java中特别简单。

如上文所述,多线程将任务划分成离散且逻辑的单元,而不是事件循环。 线程还具有远离轮询的第二个优点。 轮询通常通过循环重复监视条件来实现。 条件成立后,必须采取适当行动。 这浪费了CPU时间。 例如,考虑一下经典序列问题。 当一个线程生成数据,而另一个程序正在消耗数据时。 假设为了使问题更有趣,数据生成器必须等待消费者完成工作才能生成新数据。 轮询系统会导致消费者在等待生产者生成数据时浪费很多CPU周期。 生产者完成工作后,开始轮询,浪费更多的CPU时间等待消费者的工作完成。 很明显,这种情况不受欢迎。

为了避免轮询,Java包含由wait (、notify )和notifyAll )方法实现的进程间通信机制。 这些方法在对象中用final方法实现,因此包含在所有类中。 这三个方法仅在同步方法中调用。 尽管这些方法从计算机科学视野的方向看具有概念的高度先进性,但实际使用起来很简单。

wit ) )指示调用的线程放弃调度并进入休眠,直到其他线程进入同一线程,并调用通告)。

通告) )恢复调用同一对象中第一个等待)的线程。

恢复调用通告所有(是同一对象中的等待)的所有线程。 优先级最高的线程首先运行。

这些方法在Object中声明如下:

finalvoidwait (throwsinterruptedexception )

final void notify (

final void通知全部()

wit ) )存在的另一种形式可以定义等待时间。

下面的示例程序错误地执行了简单的生产者/消费者问题。 它由四个班组成。 q、获取同步序列的方法; Producer,用于生成排队的线程对象; Consumer,消费序列的线程对象; 然后创建PC、各个q、Producer和Consumer的小类。

//anincorrectimplementationofaproducerandconsumer。

类q {

int n;

同步输入获取(

system.out.println(got: ) n;

返回n;

}

同步化语音(intn ) {

this.n=n;

system.out.println(put: ) n;

}

}

classproducerimplementsrunnable {

q;

产品开发人员(QQ ) {

this.q=q;

newthread(this,' Producer ' ).start );

}

公共void run (}

int i=0;

while (真)。

q.put(I );

}

}

}

classconsumerimplementsrunnable {

q;

客户(QQ ) {

this.q=q;

newthread(this,' Consumer ' ).start );

}

公共void run (}

while (真)。

q.get (;

}

}

}

class PC {

publicstaticvoidmain (string args [ ] ) {

问Q q=new Q (;

新生产程序(q;

新消费者(q;

system.out.println (press control-CTO stop.';

}

}

尽管q级put (和get )方法同步,但既没有阻止生产者超越消费者,也没有阻止消费者两次消费同一序列。 这样可以得到以下错误输出。 输出取决于处理器的速度和加载的任务。

Put: 1

Got: 1

Got: 1

Got: 1

Got: 1

Got: 1

Put: 2

Put: 3

Put: 4

Put: 5

Put:

6

Put: 7

Got: 7

生产者生成1后,消费者依次获得同样的1五次。生产者在继续生成2到7,消费者没有机会获得它们。

用Java正确的编写该程序是用wait( )和notify( )来对两个方向进行标志,如下所示:

// A correct implementation of a producer and consumer.

class Q {

int n;

boolean valueSet = false;

synchronized int get() {

if(!valueSet)

try {

wait();

} catch(InterruptedException e) {

System.out.println("InterruptedException caught");

}

System.out.println("Got: " + n);

valueSet = false;

notify();

return n;

}

synchronized void put(int n) {

if(valueSet)

try {

wait();

} catch(InterruptedException e) {

System.out.println("InterruptedException caught");

}

this.n = n;

valueSet = true;

System.out.println("Put: " + n);

notify();

}

}

class Producer implements Runnable {

Q q;

Producer(Q q) {

this.q = q;

new Thread(this, "Producer").start();

}

public void run() {

int i = 0;

while(true) {

q.put(i++);

}

}

}

class Consumer implements Runnable {

Q q;

Consumer(Q q) {

this.q = q;

new Thread(this, "Consumer").start();

}

public void run() {

while(true) {

q.get();

}

}

}

class PCFixed {

public static void main(String args[]) {

Q q = new Q();

new Producer(q);

new Consumer(q);

System.out.println("Press Control-C to stop.");

}

}

内部get( ), wait( )被调用。这使执行挂起直到Producer 告知数据已经预备好。这时,内部get( ) 被恢复执行。获取数据后,get( )调用notify( )。这告诉Producer可以向序列中输入更多数据。在put( )内,wait( )挂起执行直到Consumer取走了序列中的项目。当执行再继续,下一个数据项目被放入序列,notify( )被调用,这通知Consumer它应该移走该数据。

下面是该程序的输出,它清楚的显示了同步行为:

Put: 1

Got: 1

Put: 2

Got: 2

Put: 3

Got: 3

Put: 4

Got: 4

Put: 5

Got: 5

下一节>

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。