进程间通信的方法主要有以下几种:
(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关 系 进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
(7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
而在java中我们实现多线程间通信则主要采用"共享变量"和"管道流"这两种方法
方法二 通过管道流
其中方法一有两种实现方法,即
方法一a)通过内部类实现线程的共享变量
代码如下:
01 | public class Innersharethread { |
02 | public static void main(String[] args) { |
03 | Mythread mythread = new Mythread(); |
04 | mythread.getThread().start(); |
05 | mythread.getThread().start(); |
06 | mythread.getThread().start(); |
07 | mythread.getThread().start(); |
08 | } |
09 | } |
10 | class Mythread { |
11 | int index = 0 ; |
12 | |
13 | private class InnerThread extends Thread { |
14 | public synchronized void run() { |
15 | while ( true ) { |
16 | System.out.println(Thread.currentThread().getName() |
17 | + "is running and index is " + index++); |
18 | } |
19 | } |
20 | } |
21 | |
22 | public Thread getThread() { |
23 | return new InnerThread(); |
24 | } |
25 | } |
26 | |
27 | /** |
28 | * 通过内部类实现线程的共享变量 |
29 | * |
30 | */ |
31 | public class Innersharethread { |
32 | public static void main(String[] args) { |
33 | Mythread mythread = new Mythread(); |
34 | mythread.getThread().start(); |
35 | mythread.getThread().start(); |
36 | mythread.getThread().start(); |
37 | mythread.getThread().start(); |
38 | } |
39 | } |
40 | class Mythread { |
41 | int index = 0 ; |
42 | |
43 | private class InnerThread extends Thread { |
44 | public synchronized void run() { |
45 | while ( true ) { |
46 | System.out.println(Thread.currentThread().getName() |
47 | + "is running and index is " + index++); |
48 | } |
49 | } |
50 | } |
51 | |
52 | public Thread getThread() { |
53 | return new InnerThread(); |
54 | } |
55 | } |
b)通过实现Runnable接口实现线程的共享变量
代码如下:
01 | public class Interfacaesharethread { |
02 | public static void main(String[] args) { |
03 | Mythread mythread = new Mythread(); |
04 | new Thread(mythread).start(); |
05 | new Thread(mythread).start(); |
06 | new Thread(mythread).start(); |
07 | new Thread(mythread).start(); |
08 | } |
09 | } |
10 |
11 | /* 实现Runnable接口 */ |
12 | class Mythread implements Runnable { |
13 | int index = 0; |
14 |
15 | public synchronized void run() { |
16 | while (true) |
17 | System.out.println(Thread.currentThread().getName() + "is running and |
18 | the index is " + index++); |
19 | } |
20 | } |
21 |
22 | /** |
23 | * 通过实现Runnable接口实现线程的共享变量 |
24 | |
25 | */ |
26 | public class Interfacaesharethread { |
27 | public static void main(String[] args) { |
28 | Mythread mythread = new Mythread(); |
29 | new Thread(mythread).start(); |
30 | new Thread(mythread).start(); |
31 | new Thread(mythread).start(); |
32 | new Thread(mythread).start(); |
33 | } |
34 | } |
35 |
36 | /* 实现Runnable接口 */ |
37 | class Mythread implements Runnable { |
38 | int index = 0 ; |
39 |
40 | public synchronized void run() { |
41 | while ( true ) |
42 | System.out.println(Thread.currentThread().getName() + "is running and |
43 | the index is " + index++); |
44 | } |
45 | } |
方法二(通过管道流):
代码如下:
01 | public class CommunicateWhitPiping { |
02 | public static void main(String[] args) { |
03 | /** |
04 | * 创建管道输出流 |
05 | */ |
06 | PipedOutputStream pos = new PipedOutputStream(); |
07 | /** |
08 | * 创建管道输入流 |
09 | */ |
10 | PipedInputStream pis = new PipedInputStream(); |
11 | try { |
12 | /** |
13 | * 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现 |
14 | */ |
15 | pos.connect(pis); |
16 | } catch (IOException e) { |
17 | e.printStackTrace(); |
18 | } |
19 | /** |
20 | * 创建生产者线程 |
21 | */ |
22 | Producer p = new Producer(pos); |
23 | /** |
24 | * 创建消费者线程 |
25 | */ |
26 | Consumer c = new Consumer(pis); |
27 | /** |
28 | * 启动线程 |
29 | */ |
30 | p.start(); |
31 | c.start(); |
32 | } |
33 | } |
34 |
35 | /** |
36 | * 生产者线程(与一个管道输入流相关联) |
37 | * |
38 | */ |
39 | class Producer extends Thread { |
40 | private PipedOutputStream pos; |
41 |
42 | public Producer(PipedOutputStream pos) { |
43 | this .pos = pos; |
44 | } |
45 |
46 | public void run() { |
47 | int i = 8 ; |
48 | try { |
49 | pos.write(i); |
50 | } catch (IOException e) { |
51 | e.printStackTrace(); |
52 | } |
53 | } |
54 | } |
55 |
56 | /** |
57 | * 消费者线程(与一个管道输入流相关联) |
58 | * |
59 | */ |
60 | class Consumer extends Thread { |
61 | private PipedInputStream pis; |
62 |
63 | public Consumer(PipedInputStream pis) { |
64 | this .pis = pis; |
65 | } |
66 |
67 | public void run() { |
68 | try { |
69 | System.out.println(pis.read()); |
70 | } catch (IOException e) { |
71 | e.printStackTrace(); |
72 | } |
73 | } |
74 | } |