精华内容
下载资源
问答
  • 关于线程的几种控制方式以及线程中的几种通信方式,给初学者参考,希望能有用
  • 几种进程通信方式 (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程使用。进程的血缘关系通常指父子进程关系。 (2)有名管道(named pipe):有名管道也...

    近日想总结下进程间,线程间的通信方式,在网上搜索了下,感觉写的很好,照搬过来,当做加深记忆。

    几种进程间的通信方式

    (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。

    (2)有名管道(named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间通信。

    (3)信号量(semophore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

    (4)消息队列(message queue):消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

    (5)信号(signal):信号是一种比较复杂的通信方式,用于通知接收进程某一事件已经发生。

    (6)共享内存(shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,共享内存是最快的IPC方式,它是针对其他进程间的通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。

    (7)套接字(socket):套接口也是一种进程间的通信机制,与其他通信机制不同的是它可以用于不同及其间的进程通信。

    几种线程间的通信机制

    1、锁机制

         1.1 互斥锁:提供了以排它方式阻止数据结构被并发修改的方法。

         1.2 读写锁:允许多个线程同时读共享数据,而对写操作互斥。

         1.3 条件变量:可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。

    2、信号量机制:包括无名线程信号量与有名线程信号量

    3、信号机制:类似于进程间的信号处理。

    线程间通信的主要目的是用于线程同步,所以线程没有象进程通信中用于数据交换的通信机制。


    进程和线程的区别?

    定义:
    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

    .关系
    一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
    相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

    3.区别
    进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
    1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
    2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
    3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
    4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
    4.优缺点
    线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

    展开全文
  • 线程间通信几种实现方式

    万次阅读 多人点赞 2019-01-13 07:43:41
    线程间通信几种实现方式 首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析: 题目:有两个线程A、B,A线程向一个集合...

    线程间通信的几种实现方式

    首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析:
    

    题目:有两个线程A、B,A线程向一个集合里面依次添加元素"abc"字符串,一共添加十次,当添加到第五次的时候,希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作


    方式一:使用 volatile 关键字

    基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式

    public class TestSync {
        // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
        static volatile boolean notice = false;
    
        public static void main(String[] args) {
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        notice = true;
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    if (notice) {
                        System.out.println("线程B收到通知,开始执行自己的业务...");
                        break;
                    }
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    运行结果为:
    在这里插入图片描述

    方式二:使用Object类的wait() 和 notify() 方法

    众所周知,Object类提供了线程间通信的方法:wait()notify()notifyaAl(),它们是多线程通信的基础,而这种实现方式的思想自然是线程间通信。

    注意: wait和 notify必须配合synchronized使用,wait方法释放锁,notify方法不释放锁

    public class TestSync {
        public static void main(String[] args) {
            // 定义一个锁对象
            Object lock = new Object();
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                synchronized (lock) {
                    for (int i = 1; i <= 10; i++) {
                        list.add("abc");
                        System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (list.size() == 5)
                            lock.notify();// 唤醒B线程
                    }
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    synchronized (lock) {
                        if (list.size() != 5) {
                            try {
                                lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("线程B收到通知,开始执行自己的业务...");
                    }
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    运行结果为
    在这里插入图片描述由打印结果截图可知,在线程A发出notify()唤醒通知之后,依然是走完了自己线程的业务之后,线程B才开始执行,这也正好说明了,notify()方法不释放锁,而wait()方法释放锁。

    方式三:使用JUC工具类 CountDownLatch

    jdk1.5之后在java.util.concurrent包下提供了很多并发编程相关的工具类,简化了我们的并发编程代码的书写,***CountDownLatch***基于AQS框架,相当于也是维护了一个线程间共享变量state

    public class TestSync {
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        countDownLatch.countDown();
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    if (list.size() != 5) {
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("线程B收到通知,开始执行自己的业务...");
                    break;
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    运行结果为:
    在这里插入图片描述

    使用 ReentrantLock 结合 Condition

    public class TestSync {
        public static void main(String[] args) {
            ReentrantLock lock = new ReentrantLock();
            Condition condition = lock.newCondition();
    
            List<String> list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                lock.lock();
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        condition.signal();
    
                }
                lock.unlock();
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                lock.lock();
                if (list.size() != 5) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("线程B收到通知,开始执行自己的业务...");
                lock.unlock();
            });
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            threadA.start();
        }
    }
    

    运行结果为:
    在这里插入图片描述
    显然这种方式使用起来并不是很好,代码编写复杂,而且线程B在被A唤醒之后由于没有获取锁还是不能立即执行,也就是说,A在唤醒操作之后,并不释放锁。这种方法跟 Objectwait()notify() 一样。

    方式五:基本LockSupport实现线程间的阻塞和唤醒

    LockSupport 是一种非常灵活的实现线程间阻塞和唤醒的工具,使用它不用关注是等待线程先进行还是唤醒线程先运行,但是得知道线程的名字。

    public class TestSync {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            // 实现线程B
            final Thread threadB = new Thread(() -> {
                if (list.size() != 5) {
                    LockSupport.park();
                }
                System.out.println("线程B收到通知,开始执行自己的业务...");
            });
            // 实现线程A
            Thread threadA = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        LockSupport.unpark(threadB);
                }
            });
            threadA.start();
            threadB.start();
        }
    }
    

    运行结果
    在这里插入图片描述

    展开全文
  • 几种进程通信方式 (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程使用。进程的血缘关系通常指父子进程关系。 (2)有名管道(named pipe):有名管道也...

    几种进程间的通信方式

    (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。

    (2)有名管道(named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间通信。

    (3)信号量(semophore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

    (4)消息队列(message queue):消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

    (5)信号(signal):信号是一种比较复杂的通信方式,用于通知接收进程某一事件已经发生。

    (6)共享内存(shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,共享内存是最快的IPC方式,它是针对其他进程间的通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。

    (7)套接字(socket):套接口也是一种进程间的通信机制,与其他通信机制不同的是它可以用于不同及其间的进程通信。

    几种线程间的通信机制

    1、锁机制

         1.1 互斥锁:提供了以排它方式阻止数据结构被并发修改的方法。

         1.2 读写锁:允许多个线程同时读共享数据,而对写操作互斥。

         1.3 条件变量:可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。

    2、信号量机制:包括无名线程信号量与有名线程信号量

    3、信号机制:类似于进程间的信号处理。

    线程间通信的主要目的是用于线程同步,所以线程没有象进程通信中用于数据交换的通信机制。

     

    进程和线程的区别?

    定义:
    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

    .关系
    一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
    相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

    3.区别
    进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
    1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
    2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
    3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
    4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
    4.优缺点
    线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

    展开全文
  • 几种进程通信方式 (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程使用。进程的血缘关系通常指父子进程关系。 (2)有名管道(named pipe):有名管道也...

    一、进程通信

    几种进程间的通信方式

    (1) 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。

    (2)有名管道(named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间通信。

    (3)信号量(semophore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

    (4)消息队列(message queue):消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

    (5)信号(signal):信号是一种比较复杂的通信方式,用于通知接收进程某一事件已经发生。

    (6)共享内存(shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,共享内存是最快的IPC方式,它是针对其他进程间的通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。

    (7)套接字(socket):套接口也是一种进程间的通信机制,与其他通信机制不同的是它可以用于不同及其间的进程通信。

    二、线程通信

    (1)、锁机制

     1.1 互斥锁:提供了以排它方式阻止数据结构被并发修改的方法。
    
     1.2 读写锁:允许多个线程同时读共享数据,而对写操作互斥。
    
     1.3 条件变量:可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
    

    (2)、信号量机制:包括无名线程信号量与有名线程信号量

    (3)、信号机制:类似于进程间的信号处理。

    线程间通信的主要目的是用于线程同步,所以线程没有象进程通信中用于数据交换的通信机制。

    三、二者区别

    (1)定义方面:进程是程序在某个数据集合上的一次运行活动;线程是进程中的一个执行路径。(进程可以创建多个线程)
    (2)角色方面:在支持线程机制的系统中,进程是系统资源分配的基本单位,线程是CPU调度的基本单位。
    (3)资源共享方面:进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。同时线程还有自己的栈和栈指针,程序计数器等寄存器。
    (4)独立性方面:进程有自己独立的地址空间,而线程没有,线程必须依赖于进程而存在。
    (5)开销方面。进程切换的开销较大。线程相对较小。(引入线程也出于了开销的考虑)

    展开全文
  • 线程间通信几种方式

    万次阅读 2018-03-06 11:21:39
    线程间通信方式①同步这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。参考示例:public class MyObject { synchronized public void methodA() { //do something.... } ...
  • android 线程间通信几种方式

    千次阅读 2017-02-20 17:23:15
    1.共享变量(内存) 2.管道 3.handle机制 runOnUiThread(Runnable) view.post(Runnable)
  • 线程间通信:由于多线程共享地址空间和数据空间,所以多个线程间通信是一个线程的数据可以直接提供给其他线程使用
  • JAVA线程间通信几种方式

    万次阅读 多人点赞 2017-08-12 21:55:12
    “编写两个线程,一个线程打印1~25,另一个线程打印字母A~Z,打印顺序为12A34B56C……5152Z,要求使用线程间通信。” 这是一道非常好的面试题,非常能彰显被面者关于多线程的功力,一下子就勾起了我的兴趣。这里...
  • java线程间通讯几种方式

    千次阅读 多人点赞 2021-02-04 16:38:10
    这个时候就需要线程间进行通讯 A执行完了后对B说一声,喂B,我执行完了 来康康用Java怎么实现 1、基于synchronized 2、基于reentrantLock 3、基于volatile 4、基于countDownLatch 我目前就知道这四 1、...
  • 线程间3种通信方式

    千次阅读 2010-12-22 10:14:00
    线程间通信可以通过下列三方法:1) 使用全局变量实现线程间通信:全局和静态变量是所有线程都可以访问的,所以要注意线程同步问题。MFC全局变量定义方法:方法1、自己定义一个全局变量头文件,在需要用引用的地方#...
  • Android 线程间通信有哪几种方式

    千次阅读 2016-11-13 15:06:18
    Android 线程间通信有哪几种方式
  • 线程间同步几种方式

    千次阅读 2019-03-30 15:08:19
    进程中线程同步的四常用方式: 1、 临界区(CCriticalSection) 当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到...
  • 安卓中的几种线程间通信方式

    万次阅读 2017-05-28 11:00:55
    一:Handler实现线程间通信  andriod提供了 Handler 和 Looper 来满足线程间通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。...
  • java实现线程通信几种方式

    千次阅读 2020-05-30 19:34:35
    比如大家熟知的消息中间件的实现,从某种角度上讲,就借助了多线程通信的思想,下面总结了JDK中常用的几种实现线程通信方式,提供参考 1、synchronized实现方式 可能很多小伙伴们会有疑问,synchronized是对共享...
  • 进程和线程的区别: 对于进程来说,子进程是父进程的复制品,从父进程那里获得父进程的数据空间,堆和栈的复制品。 而线程,相对于进程而言,是一个更加接近于执行体的概念,可以和同进程的其他线程之间直接共享数据...
  • java 线程间通信几种方式

    千次阅读 2017-10-11 14:12:12
    假设有两个线程,一个线程A,一个线程B,两个线程分别依次打印 1-3 三个数字即可。package Test;/** /** * @author Administrator * @createdate 2017-10-10 */ public class demo1 { public static void main...
  • 本总结我对于JAVA多线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。 二,线程间通信方式 ①同步 这里讲的同步是指多个线程通过synchronized...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 222,510
精华内容 89,004
关键字:

线程间的几种通信方式