多线程之间的通信

线程通信的概念:

  线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务在处理的过程中进行有效的把控与监督。

使用wait/notify方法实现线程间的通信(这两个方法都是object的类的方法,换句话说java为所有的对象 都提供了这两个方法)1.1.wait和notify必须配合synchronized关键字使用

2.wait方法释放锁,notify方法不释放锁。

代码1:最原始的实现方式  缺点:线程2一直在判断list的size,每增加一个判断一次

 1 package com.java.day02_notify_wait;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5
 6 public class ListAdd1 {
 7     private volatile static List list = new ArrayList();
 8
 9     public void add() {
10         list.add("nanami");
11     }
12
13     public int getSize() {
14         return list.size();
15     }
16
17     public static void main(String[] args) {
18         final ListAdd1 a = new ListAdd1();
19
20         Thread t1 = new Thread(new Runnable() {
21             public void run() {
22                 for (int i = 0; i < 10; i++) {
23                     a.add();
24                     System.out.println(Thread.currentThread().getName() + "线程增加了一个元素");
25                     try {
26                         Thread.sleep(500);
27                     } catch (InterruptedException e) {
28                         e.printStackTrace();
29                     }
30                 }
31
32             }
33         }, "t1");
34
35         Thread t2 = new Thread(new Runnable() {
36             public void run() {
37                 while(true){
38                     if(a.getSize()==5){//线程2收到通知
39                         System.out.println(Thread.currentThread().getName()+"线程收到通知:"+"list.size()=5    "+"线程停止。。。。。。。");
40                         throw new RuntimeException();
41                     }
42                 }
43
44             }
45         }, "t2");
46
47         t1.start();
48         t2.start();
49
50     }
51
52 }

运行结果:

 1 t1线程增加了一个元素
 2 t1线程增加了一个元素
 3 t1线程增加了一个元素
 4 t1线程增加了一个元素
 5 t1线程增加了一个元素
 6 Exception in thread "t2" java.lang.RuntimeException
 7 t2线程收到通知:list.size()=5    线程停止。。。。。。。
 8     at com.java.day02_notify_wait.ListAdd1$2.run(ListAdd1.java:40)
 9     at java.lang.Thread.run(Unknown Source)
10 t1线程增加了一个元素
11 t1线程增加了一个元素
12 t1线程增加了一个元素
13 t1线程增加了一个元素
14 t1线程增加了一个元素

代码2:用wait和notify实现  弊端:不时实问题
注意:先执行线程2,再执行线程1

 1 package com.java.day02_notify_wait;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5
 6 public class ListAdd2 {
 7     private volatile static List list = new ArrayList();
 8
 9     public void add(){
10         list.add("tomoe");
11     }
12
13     public int getSize(){
14         return list.size();
15     }
16
17
18     public static void main(String[] args) {
19         final Object lock = new Object();
20         final ListAdd2 list = new ListAdd2();
21
22         Thread t1 = new Thread(new Runnable() {
23             public void run() {
24                 synchronized (lock) {
25                     for (int i = 0; i < 10; i++) {
26                         list.add();
27                         System.out.println(Thread.currentThread().getName()+"线程添加了一个元素");
28                         try {
29                             Thread.sleep(500);
30                         } catch (InterruptedException e) {
31                             e.printStackTrace();
32                         }
33                         if(list.getSize()==5){
34                             System.out.println("通知已发出");
35                             lock.notify();
36                         }
37
38                     }
39                 }
40             }
41         },"t1");
42
43
44         Thread t2 = new Thread(new Runnable() {
45             public void run() {
46                 synchronized (lock) {
47                     if(list.getSize()!=5){
48                         try {
49                             lock.wait();
50                         } catch (InterruptedException e) {
51                             e.printStackTrace();
52                         }
53                     }
54                     System.out.println("收到线程通知:"+"list.size()=5"+"    线程停止。。。");
55                     throw new RuntimeException();
56                 }
57             }
58         },"t2");
59
60         t2.start();
61         t1.start();
62
63         /**
64          * 代码执行流程
65          * 1.线程2先启动,获得lock锁,执行wait语句,释放锁
66          * 2.线程1启动后获得lock锁,唤醒线程2,但是不会释放锁,当synchronized中的语句执行完后,会释放锁
67          *
68          * 如果t1先执行,则t1先获得锁,t1在执行notify时,t2并没有wait,在t1执行完之后,执行t2,此时,t2进入wait,并没有被唤醒
69          */
70
71
72     }
73
74
75 }

运行结果: 当线程1执行完后释放锁,线程2才可以执行

 1 t1线程添加了一个元素
 2 t1线程添加了一个元素
 3 t1线程添加了一个元素
 4 t1线程添加了一个元素
 5 t1线程添加了一个元素
 6 通知已发出
 7 t1线程添加了一个元素
 8 t1线程添加了一个元素
 9 t1线程添加了一个元素
10 t1线程添加了一个元素
11 t1线程添加了一个元素
12 收到线程通知:list.size()=5    线程停止。。。
13 Exception in thread "t2" java.lang.RuntimeException
14     at com.java.day02_notify_wait.ListAdd2$2.run(ListAdd2.java:55)
15     at java.lang.Thread.run(Unknown Source)

代码3:实时通知

 1 package com.java.day02_notify_wait;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.concurrent.CountDownLatch;
 6
 7 public class ListAdd3 {
 8     private volatile static List list = new ArrayList ();
 9     public void add(){
10         list.add("nanami");
11     }
12
13     public int getsize(){
14         return list.size();
15     }
16
17     private static CountDownLatch countdownlatch = new CountDownLatch(1);
18
19
20     public static void main(String[] args) {
21         final ListAdd3 list = new ListAdd3();
22
23         Thread t1 = new Thread(new Runnable() {
24             public void run() {
25                 for (int i = 0; i < 10; i++) {
26                     list.add();
27                     System.out.println(Thread.currentThread().getName()+"线程增加了一个元素");
28                     try {
29                         Thread.sleep(500);
30                     } catch (InterruptedException e) {
31                         e.printStackTrace();
32                     }
33                     if(list.getsize()==5){
34                         System.out.println("发出通知");                //private static CountDownLatch countdownlatch = new CountDownLatch(1);这里写的数字1,则下面的语句写一遍,如果为数字2,则唤醒的语句写两遍
35                         countdownlatch.countDown(); //1
36 //                        countdownlatch.notify(); //2
37
38                     }
39                 }
40             }
41         },"t1");
42
43
44         Thread t2 = new Thread(new Runnable() {
45             public void run() {
46                 if(list.getsize()!=5){
47                     try {
48                         countdownlatch.await();
49                     } catch (InterruptedException e) {
50                         e.printStackTrace();
51                     }
52                 }
53                 System.out.println("接到通知:"+"list.size()=5"+"    线程停止");
54                 throw new RuntimeException();
55             }
56         },"t2");
57
58         t1.start();
59         t2.start();
60
61     }
62
63
64
65
66
67 }

运行结果1:运行完成,程序结束

 1 t1线程增加了一个元素
 2 t1线程增加了一个元素
 3 t1线程增加了一个元素
 4 t1线程增加了一个元素
 5 t1线程增加了一个元素
 6 发出通知
 7 t1线程增加了一个元素
 8 接到通知:list.size()=5    线程停止
 9 Exception in thread "t2" java.lang.RuntimeException
10     at com.java.day02_notify_wait.ListAdd3$2.run(ListAdd3.java:54)
11     at java.lang.Thread.run(Unknown Source)
12 t1线程增加了一个元素
13 t1线程增加了一个元素
14 t1线程增加了一个元素
15 t1线程增加了一个元素

运行结果2:运行未终止

时间: 2024-08-25 13:28:02

多线程之间的通信的相关文章

多线程之间的通信实例讲解

                 多线程之间的通信实例讲解对于线程来说,说白了,就是一个函数,如果大家对于这章函数都有理解,那我对于操作系统,线程和进程间的通信会有一个新的认识!接下来我会对每一行代码进行注释,在此过程中,大家也可以对c语言有一个崭新的认识. 第一个函数,创建两个线程. #include <stdio.h>#include <pthread.h>    这个头函数要包含,因为我们后续用的函数都是系统调用,因此需要申请头函数   这样在编译的时候,就可以找到此函数的源

多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. 为了解决上述问题中的安全问题(在存放线程进行存放操作的时候, 打印线程不能对共有数据进行操作),所以应当对两个线程       操作共有数据的代码部分进行同步(使用synchronized(),来进行同步, 注意 :使用同一个对象作为同步锁. 二.等待唤醒机制. 在上述案例实现过后运行,会发现:打印

java多线程之间的通信

如何让两个线程依次执行?那如何让 两个线程按照指定方式有序交叉运行呢?四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的三个运动员各自准备,等到三个人都准备好后,再一起跑子线程完成某件任务后,把得到的结果回传给主线程1.如何让两个线程依次执行?#Copypublic static void main(String[] args) {demo1();/结果: t1>>pirnt:1t2>>pirnt:1t2>>pir

应用java多线程实现服务器端与多客户端之间的通信

应用多线程来实现服务器与多线程之间的通信的基本步骤 1.服务器端创建ServerSocket,循环调用accept()等待客户端链接 2.客户端创建一个Socket并请求和服务器端链接 3.服务器端接受客户端请求,创建socekt与该客户端建立专线链接 4.建立链接的socket在一个单独的线程上对话 5.服务器继续等待新的链接 服务器端Server.java package test.concurrent.socket; import java.io.*; import java.net.In

应用java多线程实现server端与多client之间的通信

应用多线程来实现server与多线程之间的通信的基本步骤 1.server端创建ServerSocket,循环调用accept()等待client链接 2.client创建一个Socket并请求和server端链接 3.server端接受client请求,创建socekt与该client建立专线链接 4.建立链接的socket在一个单独的线程上对话 5.server继续等待新的链接 server端Server.java package test.concurrent.socket; import

进程线程之间的通信

多进程之间有各自的内存空间,多线程是共享同一个线程的空间 多进程之间的通信 from multiprocessing import Process, Manager def func(li): li.append(1) if __name__ == "__main__": mgr = Manager() #(共享内存)管理器接口 # 代理 shared_list = mgr.list() # 在公共进程Manage中开启一个list空间,用来进程通信 # mgr.dict() # mg

VC中利用多线程技术实现线程之间的通信

文章来源:[url]http://www.programfan.com/article/showarticle.asp?id=2951[/url] 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.

vc 基于对话框多线程编程实例——线程之间的通信

 vc基于对话框多线程编程实例--线程之间的通信 实例: vc 基于对话框多线程编程实例--线程之间的通信,码迷,mamicode.com

iOS边练边学--多线程介绍、NSThread的简单实用、线程安全以及线程之间的通信

一.iOS中的多线程 多线程的原理(之前多线程这块没好好学,之前对多线程的理解也是错误的,这里更正,好好学习这块) iOS中多线程的实现方案有以下几种 二.NSThread线程类的简单实用(直接上代码) 三.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题(存钱取钱的例子,多个售票员卖票的例子) 安全隐患解决的方法 --- 互斥锁(图解)