黑马程序员-学习日记(多线程间的通信)

 ------Java EE培训、Android培训、iOS培训、期待与您交流! -------

示例:

//将资源封装成对象
class Resour
{
    String name;
    String gender;
}

//将线程执行的任务封装成对象
class Input implements Runnable
{
       private Resour r;
    Input(Resour r)
    {
        this.r = r;
    }
    public void run()
    {
        int x =0;
        while(true)
        {
            if(x==0)
            {
                r.name = "Travis";
                r.gender = "male";
            }
            else
            {
                r.name = "张妙";
                r.gender = "女性";
            }
            x = (x+1)%2;
        }
    }
}

class Output implements Runnable
{
    private Resour r;
    Output(Resour r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            System.out.println(r.name+" "+r.gender);
        }
    }
}

class myLock
{
    static Object lockA = new Object();
    static Object lockB = new Object();
}

 class mlpcDemo
{
    public static void main(String[] args)
    {
        Resour r = new Resour();
        Input in = new Input(r);
        Output out = new Output(r);
        Thread th0 = new Thread(in);
        Thread th1 = new Thread(out);

        th0.start();
        th1.start();
    }
}

于是,我们给赋值的代码块加上同步。这里要注意必须明确哪些代码是要同步的。

//将资源封装成对象
class Resour
{
    String name;
    String gender;
}

//将线程执行的任务封装成对象
class Input implements Runnable
{
    private Resour r;
    Object obj = new Object();
    Input(Resour r)
    {
        this.r = r;
    }
    public void run()
    {
        int x =0;
        synchronized(obj)
        {           while(true)
            {
                if(x==0)
                {
                    r.name = "Travis";
                    r.gender = "male";
                }
                else
                {
                    r.name = "张妙";
                    r.gender = "女性";
                }
                x = (x+1)%2;
            }
        }

    }
}

class Output implements Runnable
{
    private Resour r;
    Output(Resour r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            System.out.println(r.name+" "+r.gender);
        }
    }
}

class myLock
{
    static Object lockA = new Object();
    static Object lockB = new Object();
}

 class mlpcDemo
{
    public static void main(String[] args)
    {
        Resour r = new Resour();
        Input in = new Input(r);
        Output out = new Output(r);
        Thread th0 = new Thread(in);
        Thread th1 = new Thread(out);

        th0.start();
        th1.start();
    }
}

表面上看,赋值代码块被加上了同步,但运行的结果依然出现了姓名和性别乱搭配的情况。

于是分析原因,定义同步有两个前提,首先Input和Output这两个线程并未使用同一个锁。

其次,仔细观察下列代码:

Thread th0 = new Thread(in);
Thread th1 = new Thread(out);th0.start();th1.start();

无论Input还是Output都只有一条线程在执行!

不过,解决这个问题也十分容易。给不同线程的同步函数加上相同的锁。

需注意的错误:

 1 public void run()
 2     {
 3         int x =0;
 4         synchronized(r)  //这样会使得线程永远走此同步函数内的代码块
 5         {
 6                 while(true)
 7                 {
 8                 if(x==0)
 9                 {
10                     r.name = "Travis";
11                     r.gender = "male";
12                 }
13                 else
14                 {
15                     r.name = "张妙";
16                     r.gender = "女性";
17                 }
18                 x = (x+1)%2;
19             }
20         }
21     }   
时间: 2024-10-23 08:38:11

黑马程序员-学习日记(多线程间的通信)的相关文章

黑马程序员-学习日记(面向对象)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 1.面向对象  理解面向对象  面向对象是相对面向过程而言,面向对象和面向过程都是一种思想. 面向过程: 强调的是功能行为.代表语言:C语言. 例子:把大象装进冰箱 1.打开冰箱门.2.放入大象.3.关上冰箱门."打开"."存储"."关上"都是功能行为,在代码中的直观体现就是函数或者方法,这就是一种面向过程的以功能行为为主体的思想体现. 面向对

黑马程序员-学习日记(接口和多态)

1.继承 1-1 继承的概念 1-1-1 继承的概述 通过 extends 关键字让类与类之间产生继承关系. 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可. 多个类可以称为子类,单独这个类称为父类或者超类. 注意: ①子类可以直接访问父类中的非私有的属性和行为. ②子类无法继承父类中私有的内容.③父类怎么来的?共性不断向上抽取而来的. ExtendDemo.java class Person{ String name; int

黑马程序员-学习日记(多线程的初步认识)

 ------Java EE培训.Android培训.iOS培训.期待与您交流! ------- 进程:正在执行的应用程序.一个应用程序运行时内存分配的空间.线程:进程中一个程序执行的控制单元,一条执行路径.负责程序的执行顺序.多线程:在java虚拟机启动的时候会有一个java.exe的执行程序,即一个进程.该进程中至少有一个线程负责java程序的运行.而且这个线程运行的代码存在于main方法中. class Demo extends Thread { public void run() { f

黑马程序员-学习日记(多线程)

进程:正在执行的应用程序.一个应用程序运行时内存分配的空间.线程:进程中一个程序执行的控制单元,一条执行路径.负责程序的执行顺序. 多线程存在的意义: 程序运行中至少有两个线程在运行,一个是主函数的主线程,另一个是垃圾回收的线程. 线程创建方式一: 继承Thread类.要覆盖其run方法,调用线程的start方法. 作用:1.启动线程 2.运行run方法.目的是将自定义的代码存储在run方法中,让线程运行 cpu每次只执行一个程序,只是在快速的不同线程间切换,表现了多线程的随机性 class M

黑马程序员-学习日记(多线程安全问题和死锁认识)

------Java培训.Android培训.iOS培训.期待与您交流! ------- 安全问题产生的原因: 当多条代码语句在操作同一个共享数据时,一个线程对多条语句只执行了一部分,还没有执行完, 另一个线程参与进来执行.导致共享数据的错误. class Mlpc implements Runnable { private int ticket = 50; public void run() { while(true) { if(ticket>0) { try { Thread.sleep(2

黑马程序员-学习日记(多线程的安全)

安全产生的原因: 当多条语句在操作同一个共享数据时,一个线程对多条语句只执行了一部分,还没有执行完, 另一个线程参与进来执行.导致共享数据的错误. class Mlpc implements Runnable { private int ticket = 50; public void run() { while(true) { if(ticket>0) { try { Thread.sleep(20); //让线程进入冻结状态 } catch (Exception e) { } System.

黑马程序员-学习日记1(多线程的初步认识)

class Mlpc extends Thread //第一步.定义类继承Thread类 { private int ticket = 20; public void run() //第二步.覆写run方法,把需要被现场运行的代码都写在其中 { while(true) { if(ticket>0) { System.out.println(Thread.currentThread()+" "+ticket); } } } } class mlpcDemo { public sta

黑马程序员-学习日记(单例设计模式的两种类型)

单例设计模式:解决一个类在内存中只有一个对象 多个程序使用统一配置信息对象时,需要保证该对对象的唯一性. 保证对象唯一性的实现步骤: 1.将构造函数私有化:为了避免其他程序过多建立该对象,禁止其他程序调用该对象. 2.在类中创建一个本类对象:为了让其他程序可以访问该类对象 3.提供一个方法可以获取到该对象的方法:方便其他程序访问自定义的本类对象.(类方法的访问方式只有两种,建立对象或定义为静态方法)

黑马程序员-学习日记(反射)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.概述 JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制. 动态获取类中信息,就是java反射.可以理解为对类的解剖. 如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了此技术. 示例:获取字节