精华内容
下载资源
问答
  • JAVA多线程之线程通信方式解析一,介绍本总结我对于JAVA多线程线程之间通信方式的理解,主要以代码结合文字的方式来讨论线程通信,故摘抄了书中的一些示例代码。二,线程的.通信方式①同步这里讲的...

    JAVA多线程之线程间的通信方式解析

    一,介绍

    本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。

    二,线程间的.通信方式

    ①同步

    这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。

    参考示例:

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

    这种方式,本质上就是“共享内存”式的通信。多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。

    ②while轮询的方式

    代码如下:

    ?

    在这种方式下,线程A不断地改变条件,线程ThreadB不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。之所以说它浪费资源,是因为JVM调度器将CPU交给线程B执行时,它没做啥“有用”的工作,只是在不断地测试 某个条件是否成立。就类似于现实生活中,某个人一直看着手机屏幕是否有电话来了,而不是: 在干别的事情,当有电话来时,响铃通知TA电话来了。

    ③wait/notify机制

    代码如下:

    ?

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

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

    这里用到了Object类的 wait() 和 notify() 方法。

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

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

    这种方式的一个好处就是CPU的利用率提高了。

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

    【JAVA多线程之线程间的通信方式解析】相关文章:

    展开全文
  • 一,介绍本总结我对于JAVA多线程线程之间通信方式的理解,主要以代码结合文字的方式来讨论线程通信,故摘抄了书中的一些示例代码。二,线程通信方式①同步这里讲的同步是指多个线程通过synchronized...

    一,介绍

    本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。

    二,线程间的通信方式

    ①同步

    这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。

    参考示例:

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    public class MyObject {

    synchronized public void methodA() {

    //do something....

    }

    synchronized public void methodB() {

    //do some other thing

    }

    }

    public class ThreadA extends Thread {

    private MyObject object;

    //省略构造方法

    @Override

    public void run() {

    super.run();

    object.methodA();

    }

    }

    public class ThreadB extends Thread {

    private MyObject object;

    //省略构造方法

    @Override

    public void run() {

    super.run();

    object.methodB();

    }

    }

    public class Run {

    public static void main(String[] args) {

    MyObject object = new MyObject();

    //线程A与线程B 持有的是同一个对象:object

    ThreadA a = new ThreadA(object);

    ThreadB b = new ThreadB(object);

    a.start();

    b.start();

    }

    }

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

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

    这种方式,本质上就是“共享内存”式的通信。多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。

    ②while轮询的方式

    代码如下:

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    1 import java.util.ArrayList;

    2 import java.util.List;

    3

    4 public class MyList {

    5

    6 private List list = new ArrayList();

    7 public void add() {

    8 list.add("elements");

    9 }

    10 public int size() {

    11 return list.size();

    12 }

    13 }

    14

    15 import mylist.MyList;

    16

    17 public class ThreadA extends Thread {

    18

    19 private MyList list;

    20

    21 public ThreadA(MyList list) {

    22 super();

    23 this.list = list;

    24 }

    25

    26 @Override

    27 public void run() {

    28 try {

    29 for (int i = 0; i < 10; i++) {

    30 list.add();

    31 System.out.println("添加了" + (i + 1) + "个元素");

    32 Thread.sleep(1000);

    33 }

    34 } catch (InterruptedException e) {

    35 e.printStackTrace();

    36 }

    37 }

    38 }

    39

    40 import mylist.MyList;

    41

    42 public class ThreadB extends Thread {

    43

    44 private MyList list;

    45

    46 public ThreadB(MyList list) {

    47 super();

    48 this.list = list;

    49 }

    50

    51 @Override

    52 public void run() {

    53 try {

    54 while (true) {

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

    56 System.out.println("==5, 线程b准备退出了");

    57 throw new InterruptedException();

    58 }

    59 }

    60 } catch (InterruptedException e) {

    61 e.printStackTrace();

    62 }

    63 }

    64 }

    65

    66 import mylist.MyList;

    67 import extthread.ThreadA;

    68 import extthread.ThreadB;

    69

    70 public class Test {

    71

    72 public static void main(String[] args) {

    73 MyList service = new MyList();

    74

    75 ThreadA a = new ThreadA(service);

    76 a.setName("A");

    77 a.start();

    78

    79 ThreadB b = new ThreadB(service);

    80 b.setName("B");

    81 b.start();

    82 }

    83 }

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    在这种方式下,线程A不断地改变条件,线程ThreadB不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。之所以说它浪费资源,是因为JVM调度器将CPU交给线程B执行时,它没做啥“有用”的工作,只是在不断地测试 某个条件是否成立。就类似于现实生活中,某个人一直看着手机屏幕是否有电话来了,而不是: 在干别的事情,当有电话来时,响铃通知TA电话来了。关于线程的轮询的影响,可参考:JAVA多线程之当一个线程在执行死循环时会影响另外一个线程吗?

    这种方式还存在另外一个问题:

    轮询的条件的可见性问题,关于内存可见性问题,可参考:JAVA多线程之volatile 与 synchronized 的比较中的第一点“一,volatile关键字的可见性”

    线程都是先把变量读取到本地线程栈空间,然后再去再去修改的本地变量。因此,如果线程B每次都在取本地的 条件变量,那么尽管另外一个线程已经改变了轮询的条件,它也察觉不到,这样也会造成死循环。

    ③wait/notify机制

    代码如下:

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    1 import java.util.ArrayList;

    2 import java.util.List;

    3

    4 public class MyList {

    5

    6 private static List list = new ArrayList();

    7

    8 public static void add() {

    9 list.add("anyString");

    10 }

    11

    12 public static int size() {

    13 return list.size();

    14 }

    15 }

    16

    17

    18 public class ThreadA extends Thread {

    19

    20 private Object lock;

    21

    22 public ThreadA(Object lock) {

    23 super();

    24 this.lock = lock;

    25 }

    26

    27 @Override

    28 public void run() {

    29 try {

    30 synchronized (lock) {

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

    32 System.out.println("wait begin "

    33 + System.currentTimeMillis());

    34 lock.wait();

    35 System.out.println("wait end "

    36 + System.currentTimeMillis());

    37 }

    38 }

    39 } catch (InterruptedException e) {

    40 e.printStackTrace();

    41 }

    42 }

    43 }

    44

    45

    46 public class ThreadB extends Thread {

    47 private Object lock;

    48

    49 public ThreadB(Object lock) {

    50 super();

    51 this.lock = lock;

    52 }

    53

    54 @Override

    55 public void run() {

    56 try {

    57 synchronized (lock) {

    58 for (int i = 0; i < 10; i++) {

    59 MyList.add();

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

    61 lock.notify();

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

    63 }

    64 System.out.println("添加了" + (i + 1) + "个元素!");

    65 Thread.sleep(1000);

    66 }

    67 }

    68 } catch (InterruptedException e) {

    69 e.printStackTrace();

    70 }

    71 }

    72 }

    73

    74 public class Run {

    75

    76 public static void main(String[] args) {

    77

    78 try {

    79 Object lock = new Object();

    80

    81 ThreadA a = new ThreadA(lock);

    82 a.start();

    83

    84 Thread.sleep(50);

    85

    86 ThreadB b = new ThreadB(lock);

    87 b.start();

    88 } catch (InterruptedException e) {

    89 e.printStackTrace();

    90 }

    91 }

    92 }

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    48304ba5e6f9fe08f3fa1abda7d326ab.png

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

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

    这里用到了Object类的 wait() 和 notify() 方法。

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

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

    这种方式的一个好处就是CPU的利用率提高了。

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

    ④管道通信就是使用java.io.PipedInputStream 和 java.io.PipedOutputStream进行通信

    具体就不介绍了。分布式系统中说的两种通信机制:共享内存机制和消息通信机制。感觉前面的①中的synchronized关键字和②中的while轮询 “属于” 共享内存机制,由于是轮询的条件使用了volatile关键字修饰时,这就表示它们通过判断这个“共享的条件变量“是否改变了,来实现进程间的交流。

    而管道通信,更像消息传递机制,也就是说:通过管道,将一个线程中的消息发送给另一个。

    展开全文
  • Java多线程-线程通信

    2021-03-09 09:15:43
    通信的方式要想实现线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等等。涉及到线程之间的相互通信,分为下面四类:文件共享网络共享共享变量JDK提供的线程协调APIsuspend/resume、wait/notify...

    通信的方式

    要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等等。涉及到线程之间的相互通信,分为下面四类:

    文件共享

    网络共享

    共享变量

    JDK提供的线程协调API

    suspend/resume、wait/notify、park/unpark

    文件共享

    b1655d608c8cfd5a11e5899e46e16be2.png

    public class MainTest {

    public static void main(String[] args) {

    // 线程1 - 写入数据

    new Thread(() -> {

    try {

    while (true) {

    Files.write(Paths.get("test.log"),

    content = "当前时间" + String.valueOf(System.currentTimeMillis()));

    Thread.sleep(1000L);

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }).start();

    // 线程2 - 读取数据

    new Thread(() -> {

    try {

    while (true) {

    Thread.sleep(1000L);

    byte[] allBytes = Files.readAllBytes(Paths.get("test.log"));

    System.out.println(new String(allBytes));

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }).start();

    }

    }

    变量共享

    d0f2f64d7f3fa680903fa4c4867d02d9.png

    public class MainTest {

    // 共享变量

    public static String content = "空";

    public static void main(String[] args) {

    // 线程1 - 写入数据

    new Thread(() -> {

    try {

    while (true) {

    content = "当前时间" + String.valueOf(System.currentTimeMillis());

    Thread.sleep(1000L);

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }).start();

    // 线程2 - 读取数据

    new Thread(() -> {

    try {

    while (true) {

    Thread.sleep(1000L);

    System.out.println(content);

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }).start();

    }

    }

    网络共享

    线程协作-JDK API

    JDK中对于需要多线程协作完成某一任务的场景,提供了对应API支持。

    多线程协作的典型场景是:生产者-消费者模型。(线程阻塞、线程唤醒)

    示例:线程1去买包子,没有包子,则不再执行。线程2生产出包子,通知线程-1继续执行。

    fd6d360a11a0d0953bd164eca82c20d5.png

    API-被弃用的suspend和resume

    作用:调用suspend挂起目标线程,通过resume可以恢复线程执行。

    /** 包子店 */

    public static Object baozidian = null;

    /** 正常的suspend/resume */

    public void suspendResumeTest() throws Exception {

    // 启动线程

    Thread consumerThread = new Thread(() -> {

    if (baozidian == null) { // 如果没包子,则进入等待

    System.out.println("1、进入等待");

    Thread.currentThread().suspend();

    }

    System.out.println("2、买到包子,回家");

    });

    consumerThread.start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    consumerThread.resume();

    System.out.println("3、通知消费者");

    }

    被弃用的主要原因是,容易写出不死锁的代码。所以用wait/notify和park/unpark机制对它进行替代

    suspend和resume死锁示例

    1、同步代码中使用

    /** 死锁的suspend/resume。 suspend并不会像wait一样释放锁,故此容易写出死锁代码 */

    public void suspendResumeDeadLockTest() throws Exception {

    // 启动线程

    Thread consumerThread = new Thread(() -> {

    if (baozidian == null) { // 如果没包子,则进入等待

    System.out.println("1、进入等待");

    // 当前线程拿到锁,然后挂起

    synchronized (this) {

    Thread.currentThread().suspend();

    }

    }

    System.out.println("2、买到包子,回家");

    });

    consumerThread.start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    // 争取到锁以后,再恢复consumerThread

    synchronized (this) {

    consumerThread.resume();

    }

    System.out.println("3、通知消费者");

    }

    2、suspend比resume后执行

    /** 导致程序永久挂起的suspend/resume */

    public void suspendResumeDeadLockTest2() throws Exception {

    // 启动线程

    Thread consumerThread = new Thread(() -> {

    if (baozidian == null) {

    System.out.println("1、没包子,进入等待");

    try { // 为这个线程加上一点延时

    Thread.sleep(5000L);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    // 这里的挂起执行在resume后面

    Thread.currentThread().suspend();

    }

    System.out.println("2、买到包子,回家");

    });

    consumerThread.start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    consumerThread.resume();

    System.out.println("3、通知消费者");

    consumerThread.join();

    }

    wait/notify机制

    这些方法只能由同一对象锁的持有者线程调用,也就是写在同步块里面,否则会抛出IllegalMonitorStateException异常。

    wait方法导致当前线程等待,加入该对象的等待集合中,并且放弃当前持有的对象锁。

    notify/notifyAll方法唤醒一个或所有正在等待这个对象锁的线程。

    注意:虽然会wait自动解锁,但是对顺序有要求,如果在notify被调用之后,才开始wait方法的调用,线程会永远处于WAITING状态。

    wait/notify代码示例

    /** 正常的wait/notify */

    public void waitNotifyTest() throws Exception {

    // 启动线程

    new Thread(() -> {

    synchronized (this) {

    while (baozidian == null) { // 如果没包子,则进入等待

    try {

    System.out.println("1、进入等待");

    this.wait();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    System.out.println("2、买到包子,回家");

    }).start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    synchronized (this) {

    this.notifyAll();

    System.out.println("3、通知消费者");

    }

    }

    造成死锁的示例

    /** 会导致程序永久等待的wait/notify */

    public void waitNotifyDeadLockTest() throws Exception {

    // 启动线程

    new Thread(() -> {

    if (baozidian == null) { // 如果没包子,则进入等待

    try {

    Thread.sleep(5000L);

    } catch (InterruptedException e1) {

    e1.printStackTrace();

    }

    synchronized (this) {

    try {

    System.out.println("1、进入等待");

    this.wait();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    System.out.println("2、买到包子,回家");

    }).start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    synchronized (this) {

    this.notifyAll();

    System.out.println("3、通知消费者");

    }

    }

    park/unpark机制

    线程调用park则等待“许可”,unpark方法为指定线程提供“许可(permit)”

    不要求park和unpark方法的调用顺序。

    多次调用unpark之后,再调用park,线程会直接运行。

    但不会叠加,也就是说,连续多次调用park方法,第一次会拿到"许可"直接运行,后续调用会进入等待。

    /** 正常的park/unpark */

    public void parkUnparkTest() throws Exception {

    // 启动线程

    Thread consumerThread = new Thread(() -> {

    while (baozidian == null) { // 如果没包子,则进入等待

    System.out.println("1、进入等待");

    LockSupport.park();

    }

    System.out.println("2、买到包子,回家");

    });

    consumerThread.start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    LockSupport.unpark(consumerThread);

    System.out.println("3、通知消费者");

    }

    造成死锁的示例

    /** 死锁的park/unpark */

    public void parkUnparkDeadLockTest() throws Exception {

    // 启动线程

    Thread consumerThread = new Thread(() -> {

    if (baozidian == null) { // 如果没包子,则进入等待

    System.out.println("1、进入等待");

    // 当前线程拿到锁,然后挂起

    synchronized (this) {

    LockSupport.park();

    }

    }

    System.out.println("2、买到包子,回家");

    });

    consumerThread.start();

    // 3秒之后,生产一个包子

    Thread.sleep(3000L);

    baozidian = new Object();

    // 争取到锁以后,再恢复consumerThread

    synchronized (this) {

    LockSupport.unpark(consumerThread);

    }

    System.out.println("3、通知消费者");

    }

    伪唤醒

    警告!之前代码中用if语句来判断,是否进入等待状态,是错误的!

    官方建议应该循环中检查等待条件,原因是处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。

    伪唤醒是指线程并非因为notify、notifyall、unpark等api调用而唤醒,是更底层原因导致的。

    展开全文
  • 一个线程送水,一个线程出水:线程操作同一个资源,但操作的动作不同。两个线程操作同一资源,但操作的动作不一样。两个方法packagecn.itcast.day5.thread;//一进一出public class线程通信{public static void...

    一个线程送水,一个线程出水:多个线程操作同一个资源,但操作的动作不同。两个线程操作同一资源,但操作的动作不一样。两个方法

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    packagecn.itcast.day5.thread;//一进一出

    public class线程通信

    {public static voidmain(String[] args)

    {

    Resouce resouce= newResouce();

    Input input= newInput(resouce);

    OutPut outPut= newOutPut(resouce);

    Thread thread1= newThread(input);

    Thread thread2= newThread(outPut);

    thread1.start();

    thread2.start();

    }

    }classResouce

    {publicString name;publicString sex;

    }class Input implementsRunnable

    {

    Resouce resouce;

    Input(Resouce resouce)

    {this.resouce =resouce;

    }

    @Overridepublic voidrun()

    {int x = 1;while (true)

    {synchronized (Input.class)//两个线程的锁只要是一个object 在内存中的字节码

    {if (x == 0)

    {

    resouce.name= "peter.peng";

    resouce.sex= "boy";

    }else{

    resouce.name= "彭运松";

    resouce.sex= "男";

    }

    x= (x + 1) % 2;

    }

    }

    }

    }class OutPut implementsRunnable

    {

    Resouce resouce;

    OutPut(Resouce resouce)

    {this.resouce =resouce;

    }

    @Overridepublic voidrun()

    {while (true)

    {synchronized (Input.class) //两个线程的锁只要是一个object 在内存中的字节码

    {

    System.out.println(Thread.currentThread()+ "-----:" + resouce.name + ":" +resouce.sex);

    }

    }

    }

    }

    进水与进水的案例

    如果要达到一进一去,交替出现而不是从上一案例一样,则得用到 wait()     notify()  notityAll(),理解这几个意义

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagecn.itcast.day5.thread;2

    3 //一进一出

    4 public class线程通信5 {6 public static voidmain(String[] args)7 {8 Resouce resouce = newResouce();9 Input input = newInput(resouce);10 OutPut outPut = newOutPut(resouce);11

    12 Thread thread1 = newThread(input);13 Thread thread2 = newThread(outPut);14

    15 thread1.start();16 thread2.start();17 }18 }19

    20 classResouce21 {22 publicString name;23 publicString sex;24 boolean flag=false;25 }26

    27 class Input implementsRunnable28 {29 Resouce resouce;30

    31 Input(Resouce resouce)32 {33 this.resouce =resouce;34 }35

    36 @Override37 public voidrun()38 {39 int x = 0;40 while (true)41 {42 synchronized (resouce)//两个线程的锁只要是一个object 在内存中的字节码

    43 {44 if(resouce.flag)45 try

    46 {47 wait();48 //由于第一次flag=false 所以线程1不会等待,就会执行x==0,赋一次值,赋值完后,flag=true,这时线程149 //就会等待,同是叫醒线程2.50 //由于flag=true 则线程2不会等待,就会执行输出语句,输出完后,flag=false,这时线程2就会等待,同时叫醒线程151 //这时就会执行else语句给resource第二次赋值,赋完值后x=(x+1)%2,这里x=0,同时flag=true,线程1又等待。同时52 //第二次叫醒线程2 .............

    53 }54 catch(Exception e)55 {56 }57 if (x == 0)58 {59 resouce.name = "peter.peng";60 resouce.sex = "boy";61 } else

    62 {63 resouce.name = "彭运松";64 resouce.sex = "男";65 }66 x = (x + 1) % 2;67 resouce.flag = true;68 resouce.notify();//叫醒线程2

    69 }70 }71 }72

    73 }74

    75 class OutPut implementsRunnable76 {77 Resouce resouce;78

    79 OutPut(Resouce resouce)80 {81 this.resouce =resouce;82 }83

    84 @Override85 public voidrun()86 {87 while (true)88 {89 synchronized (resouce) //两个线程的锁只要是一个object 在内存中的字节码

    90 {91 if (!resouce.flag)92 try

    93 {94 resouce.wait();95 }96 catch(Exception e)97 {98

    99 }100 System.out.println(resouce.name + ":" +resouce.sex);101 resouce.flag = false;102 resouce.notify();//叫醒线程1

    103 }104 }105 }106 }

    多张程交替打印两个人名

    对等待线程的优化(上一程序) 对Resurce进行封装,并把set get 方法进行同步。

    生者消费者的例子

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagenet.nw.entites;2

    3 public classThreadDemo_Product_Customer {4

    5 public static voidmain(String[] args) {6

    7 Resource resource = newResource();8 Product product = newProduct(resource);9 Customer customer = newCustomer(resource);10

    11 Thread t1 = newThread(product);12 Thread t2 = newThread(customer);13 Thread t3 = newThread(product);14 Thread t4 = newThread(customer);15

    16 t1.start();17 t2.start();18 t3.start();19 t4.start();20 }21 }22

    23 classResource {24 publicString name;25 public booleanflag;26 public int count = 0;27

    28 public synchronized voidSet(String name) {29 while (true) {30 while(flag) {31 try{32 wait();33 } catch(Exception e) {34 e.printStackTrace();35 }36 }37 this.name = name + count++;38 System.out.println(Thread.currentThread().getName() + "-P:"

    39 + this.name);40 flag = true;41 notifyAll();42 }43 }44

    45 public synchronized voidgetOut() {46 while (true) {47 while (!flag) {48 try{49 wait();50 } catch(Exception e) {51 e.printStackTrace();52 }53 }54 System.out.println(Thread.currentThread().getName() + "-C:"

    55 + this.name);56 flag = false;57 notifyAll();58 }59 }60 }61

    62 class Product implementsRunnable {63 Resource resource;64

    65 Product(Resource resource) {66 this.resource =resource;67 }68

    69 @Override70 public voidrun() {71 resource.Set("pc");72 }73 }74

    75 class Customer implementsRunnable {76 Resource resource;77

    78 Customer(Resource resource) {79 this.resource =resource;80 }81

    82 @Override83 public voidrun() {84 resource.getOut();85 }86

    87 }

    两个以上线程的消费与生产关系

    JdK1.5 新特性的多线程操作

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagenet.nw.entites;2

    3 importjava.util.concurrent.locks.Condition;4 importjava.util.concurrent.locks.Lock;5 importjava.util.concurrent.locks.ReentrantLock;6

    7 public classThreadDemo_Product_Customer {8

    9 public static voidmain(String[] args) {10

    11 Resource resource = newResource();12 Product product = newProduct(resource);13 Customer customer = newCustomer(resource);14

    15 Thread t1 = newThread(product);16 Thread t2 = newThread(customer);17 Thread t3 = newThread(product);18 Thread t4 = newThread(customer);19

    20 t1.start();21 t2.start();22 t3.start();23 t4.start();24 }25 }26

    27 classResource {28 publicString name;29 public booleanflag;30 public int count = 0;31

    32 final Lock lock = newReentrantLock();33 final Condition notFull =lock.newCondition();34 final Condition notEmpty =lock.newCondition();35

    36 public voidSet(String name) {37 lock.lock();38 try{39 while (true) {40 while(flag) {41 try{42 notFull.await();43 } catch(Exception e) {44 e.printStackTrace();45 }46 }47 this.name = name + count++;48 System.out.println(Thread.currentThread().getName() + "-P:"

    49 + this.name);50 flag = true;51 notEmpty.signal();52 }53 } finally{54 lock.unlock();55 }56 }57

    58 public voidgetOut() {59 lock.lock();60 try{61 while (true) {62 while (!flag) {63 try{64 notEmpty.await();65 } catch(Exception e) {66 e.printStackTrace();67 }68 }69 System.out.println(Thread.currentThread().getName() + "-C:"

    70 + this.name);71 flag = false;72 notFull.signal();73 }74 } finally{75 lock.unlock();76 }77 }78 }79

    80 class Product implementsRunnable {81 Resource resource;82

    83 Product(Resource resource) {84 this.resource =resource;85 }86

    87 @Override88 public voidrun() {89 resource.Set("pc");90 }91 }92

    93 class Customer implementsRunnable {94 Resource resource;95

    96 Customer(Resource resource) {97 this.resource =resource;98 }99

    100 @Override101 public voidrun() {102 resource.getOut();103 }104

    105 }

    两个以上线程的生产与消费关系

    说明:Lock提供更为优秀的方法来替换synchronized    lock.lock     lock.unlock(放在finally)

    await    single   singleall  分别对应  wait notify notifyAll ,但JDK1.5后提供了codition,可以为生产消费指这不同的codition,这样两个线程或是两个以上线程就可以分开出来控制

    如果是同一个codition singleAll时就会呼醒其它的线程同时也可以是同类的线程,达不到控制的效果。

    线程的中断:其实只要控制住run方法的循环条件就可以了,但有一种情况下await()时就没有办法做了,因为根本就不会执行循环体的语句,这时要用到interruput,使线程势抛出一个异常InterruptedException,然后在验证循环体的条件。

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagenet.nw.entites;2

    3 importjava.util.concurrent.locks.Condition;4 importjava.util.concurrent.locks.Lock;5 importjava.util.concurrent.locks.ReentrantLock;6

    7 public classThreadDemo_Product_Customer {8

    9 public static voidmain(String[] args) {10

    11 Resource resource = newResource();12 Product product = newProduct(resource);13 Customer customer = newCustomer(resource);14

    15 Thread t1 = newThread(product);16 Thread t2 = newThread(customer);17 Thread t3 = newThread(product);18 Thread t4 = newThread(customer);19 t1.start();20 t2.start();21

    22 //t3.start();23 //t4.start();

    24 }25 }26

    27 classResource {28 publicString name;29 public booleanflag;30 public boolean conditionFlag = true;31 public int count = 0;32

    33 final Lock lock = newReentrantLock();34 final Condition notFull =lock.newCondition();35 final Condition notEmpty =lock.newCondition();36

    37 public voidSet(String name) {38

    39 lock.lock();40 try{41 while(conditionFlag) {42 while(flag) {43 try{44 notFull.await();45 Thread.currentThread().interrupt();//把当前的线程中断了。

    46 } catch(InterruptedException e) {47 conditionFlag = false;48 }49 }50 this.name = name + count++;51 System.out.println(Thread.currentThread().getName() + "-P:"

    52 + this.name);53 flag = true;54 notEmpty.signal();55 }56 } finally{57 lock.unlock();58 if(Thread.interrupted()) {59 System.out.println(Thread.currentThread().getName()60 + ":线程中断了。。。。。。。。。。。");61 }62 }63 }64

    65 public voidgetOut() {66

    67 lock.lock();68 try{69 while(conditionFlag) {70 while (!flag) {71 try{72 notEmpty.await();73 Thread.currentThread().interrupt();//把当前的线程中断了。

    74 } catch(InterruptedException e) {75 conditionFlag = false;76 }77 }78 System.out.println(Thread.currentThread().getName() + "-C:"

    79 + this.name);80 flag = false;81 notFull.signal();82 }83 } finally{84 lock.unlock();85 if(Thread.interrupted()) {86 System.out.println(Thread.currentThread().getName()87 + ":线程中断了。。。。。。。。。。。");88 }89 }90 }91 }92

    93 class Product implementsRunnable {94 Resource resource;95

    96 Product(Resource resource) {97 this.resource =resource;98 }99

    100 @Override101 public voidrun() {102 resource.Set("pc");103 }104 }105

    106 class Customer implementsRunnable {107 Resource resource;108

    109 Customer(Resource resource) {110 this.resource =resource;111 }112

    113 @Override114 public voidrun() {115 resource.getOut();116 }117

    118 }

    多线程安全通信的线程中断

    线程的join   setDaemon  yield

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagecn.itcast.day5.thread;2

    3 class Demo1 implementsRunnable4 {5 private int count = 100;6

    7 @Override8 public voidrun()9 {10 while (count > 0)11 {12 System.out.println(Thread.currentThread().getName() + ":" + "------peter.peng" + count--);13 Thread.yield();14 }15 }16 }17

    18 public classThreadJionYield19 {20 public static void main(String[] args) throwsInterruptedException21 {22 //SetDaemon();//设为后台线程23 //ThreadJoin();//join可以用来时加入线程,遇到一个线程的Join主线程冻结,其它的不变,只到Join这个线程结束,主线程再执行。24 //SetPriority();//设置线程的优势级

    25 Thread thread1 = new Thread(new Demo1());//yield让当前线程停止执行另一个线程。

    26 Thread thread2 = new Thread(newDemo1());27

    28 thread1.start();29 thread2.start();30 }31

    32 private static voidSetPriority()33 {34 Thread thread1 = new Thread(newRunnable()35 {36 int count = 100;37

    38 public voidrun()39 {40 while (count > 0)41 {42 System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);43 }44 }45 });46

    47 Thread thread2 = new Thread(newRunnable()48 {49 int count = 100;50

    51 public voidrun()52 {53 while (count > 0)54 {55 System.out.println(Thread.currentThread().toString() + "------peter.peng" + count--);56 }57 }58 });59

    60 thread1.start();61 thread1.setPriority(Thread.MAX_PRIORITY);//设线程的优化级

    62 thread2.start();63

    64 System.out.println(Thread.currentThread().toString());65 }66

    67 private static void ThreadJoin() throwsInterruptedException68 {69 Thread thread1 = new Thread(newRunnable()70 {71 int count = 100;72

    73 public voidrun()74 {75 while (count > 0)76 {77 System.out.println(Thread.currentThread() + "------peter.peng" + count--);78 }79 }80 });81

    82 Thread thread2 = new Thread(newRunnable()83 {84 int count = 100;85

    86 public voidrun()87 {88 while (count > 0)89 {90 System.out.println(Thread.currentThread() + "------peter.peng" + count--);91 }92 }93 });94

    95 thread1.start();96 //thread1.join();//说明thread1要主线程的执行权,这个时候主线程就会冻结了,只到它不要了才会给主线程,如果把它放在后面来执行

    97 thread2.start();98 thread1.join();//这时thread1 与thread2交才替出现,只到结束才执行主线程的方法。

    99

    100 System.out.println(Thread.currentThread() + ":main");101 }102

    103 private static voidSetDaemon()104 {105 Thread thread1 = new Thread(newRunnable()106 {107 int count = 0;108

    109 public voidrun()110 {111 while (true)112 {113 System.out.println("------peter.peng" + count++);114 }115 }116 });117

    118 Thread thread2 = new Thread(newRunnable()119 {120 int count = 0;121

    122 public voidrun()123 {124 while (true)125 {126 System.out.println("------peter.peng" + count++);127 }128 }129 });130 thread1.setDaemon(true);//设为后台线程

    131 thread2.setDaemon(true);//设为后台线程

    132 thread1.start();133 thread2.start();134 System.out.println("over");135 }136 }

    线程的Join,setDaemon yield

    展开全文
  • Python线程间如何通信

    2021-02-06 21:42:00
    我对于线程这部分知识比较...Python 中的并行计算应在个进程(而不是线程)中完成。 实例: 工作线程从队列中获取目录名称, 然后递归查找其中的所有文件并返回结果 import os, time import threading, Queue clas...
  • } 负责管道写数据线程 void *thread_fun_write(void *p) { char *buf = "12345"; int fd; fd = open("./myfifo",O_WRONLY); if(fd == -1) { printf("write fifo open fail....\n"); exit(-1); return; } while(1) {...
  • 本篇文章主要介绍的是java多线程之间如何通信,协同处理任务,以及数据共享,定时任务处理等操作。 多线程之间通信的方式 在实际开发过程中多个线程同时操作,有两种情况的,数据共享和线程协作 数据共享的方式...
  • 线程间通信及同步方法介绍:一、线程间的通信方式1、使用全局变量主要由于线程可能更改全局变量,因此全局变量最好声明为volatile。2、使用消息实现通信在Windows程序设计中,每一个线程都可以拥有自己的消息...
  • 线程与线程之间不是相互独立的个体,它们彼此之间需要相互通信和协作; 二、常用通信 2.1、CountDownLatch 定义:主线程等待其他线程,其他线程结束后,主线程才能执行(这里的主线程不一定是就是main主线程,强调的...
  • 使线程之间进行通信后,在大大提高CPU利用率的同时还会使开发人员对各个线程任务在处理的过程中进行有效的把控。2、如何实现线程间通信2.1、等待(wait)/通知机制(notify)方法 wait() 说明方法wait()的作用是使当前...
  • linux线程间通信示例

    2021-05-14 01:27:50
    缺点是如果unlock和pthread_cond_signal之间,有个低优先级的线程正在mutex上等待的话,那么这个低优先级的线程就会抢占高优先级的线程 (调用pthread_cond_wait的线程)linux 多线程通信,而这在上面的放中间的模式...
  • GUI线程 Qt应用程序exec后就会生成一个线程,这个线程就是主线程,在GUI程序中也称为GUI线程。主线程也是唯一允许...所以,对于计算量大的操作,需要放到一个单独的线程进行计算,然后通过信号槽的方式和GUI线程进行
  • 为什么会有这个锁:为了线程安全,减少python使用者的上手难度GIL 使得同一个时刻只有一个线程在一个cpu上执行字节码,无法隐射到个cpu,多核上执行。2.特殊情况下会释放GIL:达到特定字节码行数、到底特定数目...
  • Linux作为一种新兴的操作系统,几乎支持所有的Unix下常用的进程间通信方法:管道、消息队列、共享内存、信号量、套接口。1、管道管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘...
  • java多线程间通信

    2021-03-01 06:25:56
    这是多线程笔记的第5篇文章,这一章主要是学习一下线程间通信。致我亲爱的知乎读者朋友:java多线程系列的笔记已经更新了4篇,之前的文章使用了代码加文字的形式,显得枯燥,容易让人反感,从这一次开始我将不再贴...
  • C语言中的线程间通信

    2021-05-21 03:20:25
    当我调用glutMainLoop()时OpenGL会阻塞,因为我必须在后台进行一些计算,所以我创建了另一个线程.现在,OpenGL回调应将一些数据(例如,已被按下的鼠标/键的x,y位置)发送到具有临界区的另一个线程.当关键部分正在运行时,...
  • python 多线程 通信

    2020-12-18 13:32:48
    一篇文章搞定Python多进程(全)公众号:pythonislover前面写了三篇关于python多线程的文章,大概概况了多线程使用中的方法,文章链接如下:一篇文章搞懂Python多线程简单实现和GIL - ...文章南山yrg2019-05-052651浏览量...
  • [python] 多线程通信

    2021-01-13 21:25:51
    为什么要通信如果各个线程之间各干各的,确实不需要通信,这样的代码也十分的简单。但这一般是不可能的,至少线程要和主线程进行通信,不然计算结果等内容无法取回。而实际情况中要复杂的个线程需要交换数据...
  • 转自(http://blog.csdn.net/jerrying0203/article/details/45563947)本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程的众多常见重要知识点,学习后会对java多线程概念及线程间通信方式有直观...
  • 什么叫做线程间通信在1个进程中,线程往往不是孤立存在的,线程之间需要经常进行通信线程间通信的体现1个线程传递数据给另1个线程在1个线程中执行完特定任务后,转到另1个线程继续执行任务线程间通信常用方法- ...
  • 一,介绍本总结我对于java多线程线程之间通信方式的理解,主要以代码结合文字的方式来讨论线程通信,故摘抄了书中的一些示例代码。二,线程通信方式①同步这里讲的同步是指多个线程通过synchronized...
  • 一、使用while方式来实现线程之间通信packagecom.ietree.multithread.sync;importjava.util.ArrayList;importjava.util.List;public classMyList {private volatile static List list = newArrayList();public ...
  • 1,通过Handler机制主线程中定义Handler,子线程发消息,通知Handler完成UI更新,Handler对象必须定义在主线程中,如果是个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用。 另外Handler机制与...
  • 多个线程并发执行时,默认情况下cpu是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据 如何保证...
  • 线程间通信

    2021-05-23 05:40:41
    线程间通信前面一章讲了线程间同步,提到了信号量、互斥量、事件集等概念;本章接着上一章的内容,讲解线程间通信。在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的...
  • Android进程间和线程间通信方式

    千次阅读 2021-01-17 13:22:41
    进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 351,322
精华内容 140,528
关键字:

多线程之间如何进行通信